Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
一、类、对象概述 在面向对象程序设计中,把数据以及对数据的操作封装在一起,组成一个整体(对象),不同对象之间通过消息机制来通信或者同步。对于相同类型的对象进行分类、抽象后,得出共同的特征而形成了类。 类的抽象具体包括两个方面:class Car(object): #定义一个类,派生自object类(所有类的祖先,定义类时不存在其他父类就写object)
can_move=True #定义类属性
def infor(self): #定义成员方法
print("This is a car")
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self(self代表类的实例,而非类;self 不是 python 关键字,我们把他换成其他也是可以正常执行的)。
三、类属性和类方法的调用
定义了类之后,就可以用来实例化对象,并通过“对象名.成员”的方式来访问其中的数据成员或成员方法。
>>>spring=Bird() #实例化对象
>>>print(Bird.have_feather) #通过类名调用属性
>>>print(Bird.have_head) #通过对象名调用属性
>>>spring.move() #通过对象名调用方法
>
通常情况下,我们习惯使用类对象调用类中的实例方法。但如果想用类调用实例方法,不能像如下这样:
class Study:
def info(self):
print("学 Python")
#通过类名直接调用实例方法
Study.info()
运行上面代码,程序会报出如下错误:
Traceback (most recent call last):
File "D:\python3.6\demo.py", line 5, in
Study.info()
TypeError: info() missing 1 required positional argument: 'self'
其中,最后一行报错信息提示我们,调用 info() 类方式时缺少给 self 参数传参。这意味着,和使用类对象调用实例方法不同,通过类名直接调用实例方法时,Python 并不会自动给 self 参数传值。
读者想想也应该明白,self 参数需要的是方法的实际调用者(是类对象),而这里只提供了类名,当然无法自动传值。
因此,如果想通过类名直接调用实例方法,就必须手动为 self 参数传值。例如修改上面的代码为:
class Study:
def info(self):
print("学 Python")
clang = Study()
#通过类名直接调用实例方法
Study.info(clang)
再次运行程序,结果为:
学 Python
可以看到,通过手动将 clang 这个类对象传给了 self 参数,使得程序得以正确执行。实际上,这里调用实例方法的形式完全是等价于 clang.info()。
值得一提的是,上面的报错信息只是让我们手动为 self 参数传值,但并没有规定必须传一个该类的对象,其实完全可以任意传入一个参数,例如:
class Study:
def info(self):
print(self,"学 Python")
#通过类名直接调用实例方法
Study.info("zhangsan")
运行结果为:
zhangsan 学 Python
可以看到,“zhangsan” 这个字符串传给了 info() 方法的 self 参数。显然,无论是 info() 方法中使用 self 参数调用其它类方法,还是使用 self 参数定义新的实例变量,胡乱的给 self 参数传参都将会导致程序运行崩溃。
总的来说,Python 中允许使用类名直接调用实例方法,但必须手动为该方法的第一个 self 参数传递参数,这种调用方法的方式被称为“非绑定方法”。
用类的实例对象访问类成员的方式称为绑定方法,而用类名调用类成员的方式称为非绑定方法。
(此处参考)
_xxx:受保护成员;
__xxx__:系统定义的特殊成员;
__xxx:私有成员,只有类对象自己能访问,子类对象不能直接访问到这个成员,但在对象外部可以通过“对象名._类名__xxx”这样的特殊方式来访问。
注意:Python中不存在严格意义上的私有成员。