首页 > 解决方案 > Python,为什么我们可以创建在类创建中没有定义的类变量?

问题描述

假设我们有这个简单的 Python 代码

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

如果我有任何错误,请纠正我:

Class_Var 是一个类变量,对于 MyClass 对象的所有实例都是相同的。I_Var 是一个实例变量,只存在于 MyClass 对象的实例中

foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3

类变量也是类本身的属性。

MyClass.class_var ##
## 1

MyClass.I_var 应该出错,对吗?

这是否意味着类变量可以被视为类对象本身的实例变量(因为所有类都是对象)?

MyClass.new_attribute = 'foo'
print(hasattr(ObjectCreator, 'new_attribute'))

那应该返回true。和

print (MyClass.new_attribute)

应该返回 foo。

为什么我们可以创建一个未在该类的原始定义中定义的新类变量?

MyClass.new_attribute = 'foo'

与在原始定义中创建该类属性完全相同吗?

class MyClass(object):
    class_var = 1
    new_attribute = 'foo'

那么我们可以在运行时创建新的类属性吗?这如何不干扰创建类对象并将这些类变量作为类对象的实例变量的 init 构造函数?

标签: pythonclassinstance-variablesclass-variables

解决方案


通常class,对象只是另一种类型的实例type(尽管您可以使用语句的metaclass参数来更改它)。class

与大多数其他实例一样,您可以随时向对象添加任意实例属性class

类属性和实例属性是完全分开的;前者存储在class对象上,后者存储在类的实例上。

没有什么特别的__init__;它只是另一种方法,除其他外,可以将新属性附加到对象。特殊的是你通过__init__调用类创建类的新实例时会自动调用它。foo = MyClass(2)相当于

foo = MyClass.__new__(MyClass, 2)
foo.__init__(2)

班级声明

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

大致相当于

def my_class_init(self, i_var):
    self.i_var = i_var


MyClass = type('MyClass', (object,), {'class_var': 1, '__init__: my_class_init})

的 3 参数形式type允许您dict在第一次创建类时传递创建类属性的 a,但您也始终可以在事后分配属性:

MyClass = type('MyClass', (object,), {})
MyClass.class_var = 1
MyClass.__init__ = my_class_init

只是为了让你更震撼一点,调用 totype可以被认为是

MyClass = type.__new__(type, 'MyClass', (object,), {...})
MyClass.__init__('MyClass', (object,), {...})

尽管除非您定义自定义元类(通过子类化type),否则您永远不必考虑type自己拥有__new____init__方法。


推荐阅读