本文共 3072 字,大约阅读时间需要 10 分钟。
本文参考:
定义类是通过class关键字:
class Student(object): pass
__init__
方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__
方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身
Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问
class Student(object): def __init__(self, name, score): self.__name = name self.__score = score def print_score(self): print('%s: %s' % (self.__name, self.__score))
已经无法从外部访问实例变量.__name
和实例变量.__score
了:
>>> bart = Student('Bart Simpson', 59)>>> bart.__nameTraceback (most recent call last): File "", line 1, in AttributeError: 'Student' object has no attribute '__name'
在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名
class Animal(object): def run(self): print('Animal is running...')
编写Dog和Cat类时,就可以直接从Animal类继承:
class Dog(Animal): passclass Cat(Animal): pass
【注】:
对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了:
class Timer(object): def run(self): print('Start...')
我们来判断对象类型,使用type()
函数:
>>> type(123)>>> type('str') >>> type(None)
对于class的继承关系来说,使用type()
就很不方便,能用type()
判断的基本类型也可以用isinstance()
判断,并且还可以判断一个变量是否是某些类型中的一种
>>> isinstance([1, 2, 3], (list, tuple))True>>> isinstance((1, 2, 3), (list, tuple))True
总是优先使用
isinstance()
判断类型,可以将指定类型及其子类“一网打尽”。
获得一个对象的所有属性和方法,可以使用dir()
函数
>>> dir('ABC')['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
类似__xxx__
的属性和方法在Python中都是有特殊用途的,比如__len__
方法返回长度。在Python中,如果你调用len()
函数试图获取一个对象的长度,实际上,在len()
函数内部,它自动去调用该对象的__len__()
方法,所以,下面的代码是等价的:
>>> len('ABC')3>>> 'ABC'.__len__()3
getattr()
、setattr()
以及hasattr()
,我们可以直接操作一个对象的状态:
>>> class MyObject(object):... def __init__(self):... self.x = 9... def power(self):... return self.x * self.x...>>> obj = MyObject()
测试该对象的属性:
>>> hasattr(obj, 'x') # 有属性'x'吗?True>>> obj.x9>>> hasattr(obj, 'y') # 有属性'y'吗?False>>> setattr(obj, 'y', 19) # 设置一个属性'y'>>> hasattr(obj, 'y') # 有属性'y'吗?True>>> getattr(obj, 'y') # 获取属性'y'19>>> obj.y # 获取属性'y'19
>>> hasattr(obj, 'power') # 有属性'power'吗?True>>> getattr(obj, 'power') # 获取属性'power'>>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn>>> fn # fn指向obj.power >>>> fn() # 调用fn()与调用obj.power()是一样的81
在class中定义属性,这种属性是类属性,归Student
类所有:
class Student(object): name = 'Student'
定义了一个类属性后,这个属性虽然归类所有,类的所有实例都可以访问到:
>>> class Student(object):... name = 'Student'...>>> s = Student() # 创建实例s>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性Student>>> print(Student.name) # 打印类的name属性Student>>> s.name = 'Michael' # 给实例绑定name属性>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性Michael>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问Student>>> del s.name # 如果删除实例的name属性>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了Student
在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
转载地址:http://vuhpi.baihongyu.com/