简体   繁体   English

在子类中设置父属性

[英]Setting parent attributes in child class

It has just dawned on me that I can set an attribute of a child class that only it's parent uses 我刚刚意识到我可以设置仅其父级使用的子级的属性

In [34]: class A:
    ...:     def __init__(self):
    ...:         pass
    ...:
    ...:     def a(self):
    ...:         print(f'b = {self.b}')
    ...:
    ...: class B(A):
    ...:     def __init__(self):
    ...:         super(B, self).__init__()
    ...:         self.b = 1
    ...:

In [35]: b = B()
    ...: b.a()
b = 1

This implementation seems counterintuitive and something feels wrong about it but I'm not quite sure what it is. 这种实现似乎违反直觉,对此有些不妥,但我不太确定它是什么。

I would think that the following makes more sense 我认为以下更有意义

In [38]: class A:
    ...:     def __init__(self, b):
    ...:         self.b = b
    ...:
    ...:     def a(self):
    ...:         print(f'b = {self.b}')
    ...:
    ...: class B(A):
    ...:     def __init__(self):
    ...:         super(B, self).__init__(1)
    ...:

In [39]: b = B()
    ...: b.a()
b = 1

Are there use cases where the former would be a more recommended implementation than the latter? 在某些用例中,前者会比后者更推荐实施吗?

Conceptually, you are doing two different things. 从概念上讲,您正在做两种不同的事情。 In the first case, you have something like an abstract class; 在第一种情况下,您有一个类似抽象类的东西。 in other words, a base class which is not meant to be instantiated alone, because the definitions of certain attributes are "missing"; 换句话说,一个基类不是要单独实例化的,因为某些属性的定义是“缺失的”; it is understood that subclasses will implement those attributes. 可以理解,子类将实现那些属性。

The more idiomatic way to do something like this would be to mark A as an abstract base class using the abc module, for example: 做这种事情的更惯用的方法是使用abc模块将A标记为抽象基类 ,例如:

from abc import ABCMeta, abstractmethod

class A(metaclass=ABCMeta):

    @property
    @abstractmethod
    def x(self):
        pass

    def print_me(self):
        print(f'x = {self.x}')

class B(A):

    @property
    def x(self):
        return 1

A().print_me()

The output will then be: 输出将是:

TypeError: Can't instantiate abstract class A with abstract methods x

On the other hand, this works: 另一方面,这有效:

B().print_me()  # prints x = 1

By doing this, you signal clearly that a subclass must override the x property, otherwise the print_me function won't work. 这样,您可以清楚地表明子类必须重写x属性,否则print_me函数将无法工作。

Moving to the second case, you have a concrete base class and subclass, with the subclass acting something like a constraint on the nature of instances that can be created. 转到第二种情况,您有一个具体的基类和子类,子类的作用类似于对可创建实例性质的约束。 In this case, a standalone instance of A is perfectly valid; 在这种情况下, A的独立实例完全有效; it is just that instances of B provide the additional guarantee that a specific attribute will always be a certain value (or, at least, be initialised to a certain value, if you intend your class to be mutable). 只是B实例提供了额外的保证,即特定的属性将始终为某个值(或者,如果您打算使您的类可变,则至少将其初始化为某个值)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM