Python,为什么我们可以创建 class 个在 class 创建时未定义的变量?
Python, how come we can create class variables that were not defined in class creation?
假设我们有这个简单的 Python 代码
class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
如果我有任何错误,请纠正我:
Class_Var 是一个 class 变量,它对于 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
Class 变量也是 class 本身的属性。
MyClass.class_var ##
## 1
MyClass.I_var应该会出错,对吗?
这是否意味着 class 变量可以被视为 class 对象本身的实例变量(因为所有 class 都是对象)?
MyClass.new_attribute = 'foo'
print(hasattr(ObjectCreator, 'new_attribute'))
那应该 return 正确。并且
print (MyClass.new_attribute)
应该return foo.
为什么我们可以创建一个新的 class 变量,而该 class 的原始定义中并未定义该变量?
是
MyClass.new_attribute = 'foo'
与在原始定义中创建 class 属性完全相同?
class MyClass(object):
class_var = 1
new_attribute = 'foo'
所以我们可以在运行时创建新的 class 属性?这如何不干扰创建 class 对象并将那些 class 变量作为 class 对象的实例变量的 init 构造函数?
A class
对象只是另一种类型的实例,通常是 type
(尽管您可以使用 metaclass
参数将其更改为 class
语句) .
与大多数其他实例一样,您可以随时向 class
对象添加任意实例属性。
Class属性和实例属性是完全分开的;前者存储在 class
对象上,后者存储在 class.
的实例上
__init__
没什么特别的;它只是另一种方法,除其他外,可以将新属性附加到对象。 是的特别之处在于,当您通过调用class。 foo = MyClass(2)
等同于
foo = MyClass.__new__(MyClass, 2)
foo.__init__(2)
class声明
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})
type
的 3 参数形式允许您在首次创建 class 时传递创建 class 属性的 dict
,但您始终可以分配属性事后也是:
MyClass = type('MyClass', (object,), {})
MyClass.class_var = 1
MyClass.__init__ = my_class_init
只是让你的想法更 一点,对 type
的调用可以被认为是
MyClass = type.__new__(type, 'MyClass', (object,), {...})
MyClass.__init__('MyClass', (object,), {...})
尽管除非你定义自定义元class(通过subclassing type
),你永远不必考虑type
本身有__new__
和 __init__
方法。
Does that mean that class variables can be considered like instance variables of the class object itself (since all classes are objects) ?
是的。
How come we can create a new class variable that was not defined in the original definition for that class?
因为Python是动态语言。一个 class 可以在 运行 时间创建 - 事实上,它 是 在 运行 时间创建的,而你 运行 Python 交互。
So we can create new class attributes at runtime?
是的,除非 metaclass(class 的 class)禁止它。
How does that not interfere with the init constructor that creates the class object and has those class variables as instance variables of the class object?
唯一的规则是您不能使用尚未定义或已删除的内容:
>>> class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
self.j_var = self.class_var + 1
>>> a = MyClass(2)
>>> del MyClass.class_var
>>> b = MyClass(3)
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
b = MyClass(3)
File "<pyshell#36>", line 6, in __init__
self.j_var = self.class_var + 1
AttributeError: 'MyClass' object has no attribute 'class_var'
这里没有魔法:任何东西都只能存在于它的定义点和它的破坏点之间。 Python 允许您随时为对象添加属性,除了某些 classes(例如 object
)禁止它。
使用 class MyClass
的前一个 a
对象,你可以这样做:
a.z_var = 12
从那时起,z_var
将成为 a
的属性,但相同 class 的其他对象将没有它。
只是object
禁止:
>>> o = object()
>>> o.x=1
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
o.x=1
AttributeError: 'object' object has no attribute 'x'
假设我们有这个简单的 Python 代码
class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
如果我有任何错误,请纠正我:
Class_Var 是一个 class 变量,它对于 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
Class 变量也是 class 本身的属性。
MyClass.class_var ##
## 1
MyClass.I_var应该会出错,对吗?
这是否意味着 class 变量可以被视为 class 对象本身的实例变量(因为所有 class 都是对象)?
MyClass.new_attribute = 'foo'
print(hasattr(ObjectCreator, 'new_attribute'))
那应该 return 正确。并且
print (MyClass.new_attribute)
应该return foo.
为什么我们可以创建一个新的 class 变量,而该 class 的原始定义中并未定义该变量?
是
MyClass.new_attribute = 'foo'
与在原始定义中创建 class 属性完全相同?
class MyClass(object):
class_var = 1
new_attribute = 'foo'
所以我们可以在运行时创建新的 class 属性?这如何不干扰创建 class 对象并将那些 class 变量作为 class 对象的实例变量的 init 构造函数?
A class
对象只是另一种类型的实例,通常是 type
(尽管您可以使用 metaclass
参数将其更改为 class
语句) .
与大多数其他实例一样,您可以随时向 class
对象添加任意实例属性。
Class属性和实例属性是完全分开的;前者存储在 class
对象上,后者存储在 class.
__init__
没什么特别的;它只是另一种方法,除其他外,可以将新属性附加到对象。 是的特别之处在于,当您通过调用class。 foo = MyClass(2)
等同于
foo = MyClass.__new__(MyClass, 2)
foo.__init__(2)
class声明
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})
type
的 3 参数形式允许您在首次创建 class 时传递创建 class 属性的 dict
,但您始终可以分配属性事后也是:
MyClass = type('MyClass', (object,), {})
MyClass.class_var = 1
MyClass.__init__ = my_class_init
只是让你的想法更 一点,对 type
的调用可以被认为是
MyClass = type.__new__(type, 'MyClass', (object,), {...})
MyClass.__init__('MyClass', (object,), {...})
尽管除非你定义自定义元class(通过subclassing type
),你永远不必考虑type
本身有__new__
和 __init__
方法。
Does that mean that class variables can be considered like instance variables of the class object itself (since all classes are objects) ?
是的。
How come we can create a new class variable that was not defined in the original definition for that class?
因为Python是动态语言。一个 class 可以在 运行 时间创建 - 事实上,它 是 在 运行 时间创建的,而你 运行 Python 交互。
So we can create new class attributes at runtime?
是的,除非 metaclass(class 的 class)禁止它。
How does that not interfere with the init constructor that creates the class object and has those class variables as instance variables of the class object?
唯一的规则是您不能使用尚未定义或已删除的内容:
>>> class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
self.j_var = self.class_var + 1
>>> a = MyClass(2)
>>> del MyClass.class_var
>>> b = MyClass(3)
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
b = MyClass(3)
File "<pyshell#36>", line 6, in __init__
self.j_var = self.class_var + 1
AttributeError: 'MyClass' object has no attribute 'class_var'
这里没有魔法:任何东西都只能存在于它的定义点和它的破坏点之间。 Python 允许您随时为对象添加属性,除了某些 classes(例如 object
)禁止它。
使用 class MyClass
的前一个 a
对象,你可以这样做:
a.z_var = 12
从那时起,z_var
将成为 a
的属性,但相同 class 的其他对象将没有它。
只是object
禁止:
>>> o = object()
>>> o.x=1
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
o.x=1
AttributeError: 'object' object has no attribute 'x'