Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从子类主体访问父类属性_Python_Python 3.x - Fatal编程技术网

Python 从子类主体访问父类属性

Python 从子类主体访问父类属性,python,python-3.x,Python,Python 3.x,我有一个classKlass,带有class属性my_list。我有它的一个子类subklas,其中我想有一个class属性my_list,它是父类中相同属性的修改版本: class Klass(): my_list = [1, 2, 3] class SubKlass(Klass): my_list = Klass.my_list + [4, 5] # this works, but i must specify parent class explicitly #m

我有一个class
Klass
,带有class属性
my_list
。我有它的一个子类
subklas
,其中我想有一个class属性
my_list
,它是父类中相同属性的修改版本:

class Klass():
    my_list = [1, 2, 3]


class SubKlass(Klass):
    my_list = Klass.my_list + [4, 5] # this works, but i must specify parent class explicitly
    #my_list = super().my_list + [4, 5] # SystemError: super(): __class__ cell not found
    #my_list = my_list + [4, 5] # NameError: name 'my_list' is not defined 


print(Klass.my_list)
print(SubKlass.my_list)
那么,有没有一种方法可以访问父类属性而不指定其名称

更新:


Python问题跟踪程序上存在错误:。让我们希望它会在某个时刻出现。

从课堂的主体来看是没有办法的;从self可用的上下文(或类本身)中,您可以检查
\uuuuuuuuuuuuuuuuu
您不能检查

类定义在Python中的工作原理如下

  • 解释器看到一个
    class
    语句,后面跟着一块代码

  • 它创建一个新的名称空间,并在名称空间中执行该代码

  • 它调用带有结果名称空间、类名、基类和元类(如果适用)的
    类型
    内置

  • 它将结果分配给类的名称

  • 在类定义中运行代码时,您不知道基类是什么,因此无法获取它们的属性

    您可以做的是在定义类之后立即修改它


    编辑:这里有一个小类装饰器,可以用来更新属性。这个想法是你给它一个名字和一个函数。它查看类的所有基类,并获取它们的具有该名称的属性。然后使用从基类继承的值列表和在子类中定义的值调用函数。此调用的结果绑定到名称

    代码可能更有意义:

    >>> def inherit_attribute(name, f):
    ...     def decorator(cls):
    ...             old_value = getattr(cls, name)
    ...             new_value = f([getattr(base, name) for base in cls.__bases__], old_value)
    ...             setattr(cls, name, new_value)
    ...             return cls
    ...     return decorator
    ... 
    >>> def update_x(base_values, my_value):
    ...    return sum(base_values + [my_value], tuple())
    ... 
    >>> class Foo: x = (1,)
    ... 
    >>> @inherit_attribute('x', update_x)
    ... class Bar(Foo): x = (2,)
    ... 
    >>> Bar.x
    (1, 2)
    
    其思想是将
    x
    定义为
    (2,)
    栏中。然后,装饰者将浏览
    Bar
    的子类,找到它们的所有
    x
    s,并用它们调用
    update\ux
    。所以它会打电话来

    update_x([(1,)], (2,))
    

    它通过连接它们来组合它们,然后再次将它们绑定回
    x
    。这有意义吗?

    您可以使用元类或类装饰器。下面是如何在Python 2.x中使用元类:

    class Klass(object):
        my_list = [1, 2, 3]
    
    class KlassMeta(type):
    
        def __new__(cls, name, bases, attrs):
            # grab last base class, which in this case is Klass
            attrs['my_list'] = bases[-1].my_list + [4, 5]
            return super(KlassMeta, cls).__new__(cls, name, bases, attrs)
    
    class SubKlass(Klass):
        __metaclass__ = KlassMeta
    
    对于Python 3,您可以使用较新的语法声明元类:

    class SubKlass(Klass, metaclass=KlassMeta):
        pass
    

    正如你从其他回答中看到的,比如katriealex的回答:不,你不能。至少不容易

    问:你到底想做什么


    问:为什么要这样做?

    正如@katrielex所回答的那样,
    在创建类之前,默认情况下我的列表不在命名空间中。但是,在Python 3中,如果您想深入研究元类,可以手动将
    my_list
    添加到名称空间:

    class Meta(type):
        def __prepare__(name, bases, **kwds):
            print("preparing {}".format(name), kwds)
            my_list = []
            for b in bases:
                if hasattr(b, 'my_list'):
                    my_list.extend(b.my_list)
            return {'my_list': my_list}
    
    class A(metaclass=Meta):
        my_list = ["a"]
    
    class B(A):
        my_list.append(2)
    
    print(A().my_list)
    print(B().my_list)
    
    请注意,这个示例可能还不能很好地处理菱形继承结构


    在中定义了新的
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
    属性。

    否,
    self
    不可用。否则我可以使用
    super()
    是的,我知道self在类的主体中不可用。这就是我这么说的原因。如果你不想费心去正确地阅读答案,为什么要问这个问题呢?注意元类劫持了#3,甚至可以在传递给
    type
    之前修改
    基。所以,是的,你不能。是的,这是有道理的。我自己也这么想(通过元类),但扩展继承列表只是一个例子。您可能希望从列表中删除一些项目,而不是扩展列表。或者没有列表,但有其他类型。。。谢谢你的详尽回答@warwaruk好吧,这个想法是你可以编写自己的
    update\ux
    来做这些事情。哦,Ruby允许您在类定义中引用类。但是它看起来像Perl,所以它不全是好的=p@warwaruk例如,
    def update_x(base_values,out=base_values[0];out.pop(0);返回
    。或者,我不知道,设置交集:
    def update\ux(基本值,我的值):返回set.union(*基本值)。交集(我的值)
    。或者别的什么。请不要鼓励人们不必要地使用元类。元类很复杂,任何人认为需要元类的时候,都应该避免使用。大多数人不需要知道元类是如何工作的。Python有一个很好的特性,Alex Martelli称之为“数据继承”。在
    \uuuu init\uuuu
    中,我可以编写
    self.setting1=self.setting1+5
    ,其中
    setting1
    是一个类属性。它甚至可能是父类属性。在后一个示例中,我没有使用任何特殊代码,类属性中的按名称查找是自动完成的。我希望在类正文中使用相同的功能。@warvariuc,它将创建一个名为
    self.setting1
    的实例属性,然后在任何类属性前面访问该属性。所以,尽管这在某些情况下会有所帮助,但它不会让人们设置类属性。。。