python类属性及其初始化

Python class attributes and their initialization

我对python很陌生,在这段时间里我在探索课程。我有一个关于类内属性和变量的问题:通过类内的q=1和通过__init__内的self.q=1定义属性有什么区别?例如,以下两种可能性有什么区别?

1
2
3
4
5
6
class MyClass1:
    q=1
    def __init__(self,p):
        self.p=p
    def AddSomething(self,x):
        self.q = self.q+x

1
2
3
4
5
6
class MyClass2:
    def __init__(self,p):
        self.q=1
        self.p=p
    def AddSomething(self,x):
        self.q = self.q+x

例如的输出:

1
2
3
4
5
6
7
8
>>> my=MyClass1(2)
>>> my.p
2
>>> my.q
1
>>> my.AddSomething(7)
>>> my.q
8

不取决于是否使用MyClass1MyClass2。在MyClass1MyClass2中都没有发生错误。


类以及它们在Python中的实例使用类似字典的数据结构来存储信息。

因此,对于每个类定义,将在存储类级信息(类变量)的位置分配一个字典。对于该特定类的每个实例,将在存储实例特定信息(实例变量)的位置分配一个单独的字典(self)。

所以现在的下一个问题是:如何执行特定名称的查找??

这个问题的答案是,如果您通过某个实例访问这些名称,那么将首先搜索特定于实例的字典,如果在那里没有找到该名称,那么将搜索类字典以查找该名称。因此,如果在两个级别上定义了相同的值,则将覆盖前一个级别。

请注意,当您编写d['key']=val(其中d是字典)时,如果尚未存在,则"key"将自动添加到字典中。否则,当前值将被覆盖。在阅读进一步的解释之前,请记住这一点。

现在让我们来看看您用来描述问题的代码:

MyCase1

1
2
3
4
5
6
class MyClass1:
    q=1
    def __init__(self,p):
        self.p=p
    def AddSomething(self,x):
        self.q = self.q+x
1
2
3
4
1. my = Myclass1(2) #create new instance and add variables to it.

    MyClass = {"q" : 1}
    my = {"p" : 2}
1
2. my.p    # =2, p will be taken from Dictionary of my-instance.
1
3. my.q    # =1, q will be takn from MyClass dict. (Not present in dictionary of my-instance).
1
2
3
4
5
6
7
8
9
10
11
4. my.AddSomething(7) # This method access the value of q (using self.q) first
                      # which is not defined in my dict and hence will be taken
                      # from dictionary of MyClass. After the addition operation,
                      # the sum is being stored in self.q. Note that now we are
                      # adding the name q to Dictionary of my-instance and hence                  
                      # a new memory space will be created in Dictionary of my-instance
                      # and the future references to self.q will fetch the value
                      # of self.q from dictionary of my-instance.

    MyClass = {"q" : 1}
    my = {"p" : 2,"q" : 8}
1
5. my.q   # =8, q now is available in dictionary of my-instance.

类内部的q=1是一个类属性,与整个类相关联,而不是类的任何特定实例。它最明显的访问方式是使用类本身:MyClass1.q

实例属性直接分配给一个类的实例,通常在__init__中,通过分配给self来分配(例如使用self.p = p来分配),但您可以随时将属性分配给一个实例。

类属性可以使用类绑定(MyClass.q或实例绑定(my.q读取,前提是它不被同名的实例属性隐藏)。但是,只能使用类绑定来设置它们。使用实例绑定设置值总是修改实例属性,必要时创建它。考虑这个例子:

1
2
3
4
5
6
7
8
9
10
>>> a = MyClass1()
>>> a.q
1
>>> a.q = 3    # Create an instance attribute that shadows the class attribute
3
>>> MyClass1.q
1
>>> b = MyClass1()
>>> b.q   # b doesn't have an instance attribute q, so access the class's
1


此类中q属性之间最显著的区别是,在MyClass1实现中,变量将在该类的所有实例中共享,而在MyClass2中,变量仅在该特定对象的范围内可见。

一些文档:https://docs.python.org/2/tutorial/classes.html类和实例变量