Python作为动态语言,跟静态语言如c/c++有很大区别,其中的一个重要的特性就是Python的变量无需声明直接可用。同样,类的成员变量无需声明,直接可用。目的是为了动态语言跟灵活,在思路想到的时候能及时添加成员,而无需在回到类声明的地方,添加成员。但是,同为动态语言,类的成员变量和实例成员变量,生命周期有很大的区别,我们以一个简单的小例子说明:
class student(object): '''我们声明一个学生类,希望它有‘姓名’和‘性别’两个属性''' sex = 'male' '''其中’性别‘这个属性,我们在类中赋值 ''' def __init__(self, name): '''其中‘姓名’这个属性,我们动态赋值,注意观察name属性合适创建 self._name = name stu = student('zhang') print(dir(stu)) '''我们用Python内置函数dir()查看类的所有属性,方法''' print(dir(student)) '''我们用Python内置函数dir()查看实例的所有属性,方法'''
通过观察我们发现,实例stu包含2个我们创建的成员,name和sex,这说明实例的属性,不需要声明,在需要用的时候赋值就可以(按照c/c++的思路,student类没有name成员,而Python的理想是,需要用name成员时,直接赋值)
这正是Python动态语言的特性,变量无需声明,应为,Python是解释语言,边解释边创建变量。
通过观察我们发现,类student只有sex成员,没有name成员,这也是动态语言的特性,应为类本质也是个对象(Python一切皆对象),执行类的时候,只声明,不执行__init()__,什么时候执行初始化函数呢?当我们实例一个对象的时候,这说明,动态创建类属性只属于对象,不属于类自己。我们在最后的dir()内置函数输出中再次验证:
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_name', 'sex']
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'sex']
Process finished with exit code 0
总结:Python是动态语言,类的成员变量无需声明,想到即用,但是,要区分类的属性和实例的属性,动态添加的属性只属于某个实例,不属于类。
另外,对应类变量和实例变量的是:类的三种方法,类方法,实例方法,静态方法。
至于区别,类方法,在声明类可用,实例也可用,但是实例方法只能在实例了一个类之后,才能使用实例方法。
动态给实例绑定方法,得到实例方法,但是该方法只属于实例,不属于类,所以对其他实例不起作用,所以我们开始思考python是否支持,给类绑定方法,确实支持。
利用 __slot__ 可以指定哪些属性可以绑定,那些属性不能绑定。
静态方法
静态方法是一种普通函数,就位于类定义的命名空间中,它不会对任何实例类型进行操作。使用装饰器@staticmethod定义静态方法。类对象和实例都可以调用静态方法。
class Foo:
def __init__(self, name):
self.name = name
def hi(self):
print self.name
@staticmethod
def add(a, b):
print a + b
if __name__ == '__main__':
foo01 = Foo('letian')
foo01.hi()
foo01.add(1,2)
Foo.add(1, 2)
运行结果如下:
letian
3
3
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
测试结果
下面说说区别,实例方法隐含的参数为类实例self,而类方法隐含的参数为类本身cls。
静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。
所以逻辑上,类方法应当只被类调用,实例方法实例调用,静态方法两者都能调用。主要区别在于参数传递上的区别,实例方法悄悄传递的是self引用作为参数,而类方法悄悄传递的是cls引用作为参数