为什么属性引用在 Python 继承中表现得像这样? [英] Why do attribute references act like this with Python inheritance?

查看:37
本文介绍了为什么属性引用在 Python 继承中表现得像这样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下看起来很奇怪.. 基本上,somedata 属性似乎在从 the_base_class 继承的所有类之间共享.

The following seems strange.. Basically, the somedata attribute seems shared between all the classes that inherited from the_base_class.

class the_base_class:
    somedata = {}
    somedata['was_false_in_base'] = False


class subclassthing(the_base_class):
    def __init__(self):
            print self.somedata


first = subclassthing()
{'was_false_in_base': False}
first.somedata['was_false_in_base'] = True
second = subclassthing()
{'was_false_in_base': True}
>>> del first
>>> del second
>>> third = subclassthing()
{'was_false_in_base': True}

__init__ 函数中定义 self.somedata 显然是解决这个问题的正确方法(所以每个类都有它自己的 somedata dict) - 但这种行为何时是可取的?

Defining self.somedata in the __init__ function is obviously the correct way to get around this (so each class has it's own somedata dict) - but when is such behavior desirable?

推荐答案

你说得对,somedata 在类的所有实例及其子类之间共享,因为它是在类 中创建的定义时间.线

You are right, somedata is shared between all instances of the class and it's subclasses, because it is created at class definition time. The lines

somedata = {}
somedata['was_false_in_base'] = False

在定义类时执行,即当解释器遇到 class 语句时 - 在创建实例时执行(想想 Java 中的静态初始化块).如果属性在类实例中不存在,则检查类对象的属性.

are executed when the class is defined, i.e. when the interpreter encounters the class statement - not when the instance is created (think static initializer blocks in Java). If an attribute does not exist in a class instance, the class object is checked for the attribute.

在定义类的时候,你可以运行任意代码,像这样:

At class definition time, you can run arbritrary code, like this:

 import sys
 class Test(object):
     if sys.platform == "linux2":
         def hello(self):
              print "Hello Linux"
     else:
         def hello(self):
              print "Hello ~Linux"

在 Linux 系统上,Test().hello() 将打印 Hello Linux,在所有其他系统上,将打印其他字符串.

On a Linux system, Test().hello() will print Hello Linux, on all other systems the other string will be printed.

相反,__init__ 中的对象是在实例化时创建的,并且只属于实例(当它们被分配给 self 时):

In constrast, objects in __init__ are created at instantiation time and belong to the instance only (when they are assigned to self):

class Test(object):
    def __init__(self):
        self.inst_var = [1, 2, 3]

在类对象而不是实例上定义的对象在许多情况下很有用.例如,您可能希望缓存类的实例,以便可以共享具有相同成员值的实例(假设它们应该是不可变的):

Objects defined on a class object rather than instance can be useful in many cases. For instance, you might want to cache instances of your class, so that instances with the same member values can be shared (assuming they are supposed to be immutable):

class SomeClass(object):
    __instances__ = {}

    def __new__(cls, v1, v2, v3):
        try:
            return cls.__insts__[(v1, v2, v3)]
        except KeyError:
            return cls.__insts__.setdefault(
               (v1, v2, v3), 
               object.__new__(cls, v1, v2, v3))

大多数情况下,我将类主体中的数据与元类或泛型工厂方法结合使用.

Mostly, I use data in class bodies in conjunction with metaclasses or generic factory methods.

这篇关于为什么属性引用在 Python 继承中表现得像这样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆