1.类和实例

 1 #!/usr/bin/python3
 2 
 3 class Student(object):
 4 #表示该类从哪个类继承下来的,如没有合适的继承类,就是用object类
 5 #这是所有类最终都会继承的类
 6     def __init__(self,name,score):
 7         self.name = name
 8         self.score = score
 9     def print_score(self):
10         print('%s:%s' % (self.name, self.score))
11 
12 b = Student('Chb', 100)   #创建实例
13 print(b.name)
14 print(b.score)
15 print(b.print_score())

Python 面向对象编程 随笔 第1张

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self

self代表类的实例,而非类,表示创建的实例本身

 

2.获取对象信息

当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?

使用type()

返回对应的class类型

Python 面向对象编程 随笔 第2张

使用isinstance()

对于class的继承关系来说,使用type()就很不方便。isinstance()就可以告诉我们,一个对象是否是某种类型。

Python 面向对象编程 随笔 第3张

总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。

使用dir()

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list

Python 面向对象编程 随笔 第4张

 

__slots__

在Python中,定义一个class类并创建了一个class的实例后,可以给该实例绑定任何属性和方法,这是动态语言的灵活性

Python 面向对象编程 随笔 第5张

但是,给一个实例绑定的方法,对另一个实例是不起作用的

Python 面向对象编程 随笔 第6张

如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加nameage属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性

Python 面向对象编程 随笔 第7张

由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

 

@property

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查。把一个方法变成属性调用

 1 #!/usr/bin/python3
 2 
 3 class Student(object):
 4     @property
 5     def score(self):
 6         return self._score
 7     @score.setter
 8     def score(self, value):
 9         if not isinstance(value, int):
10             raise ValueError('分数必须是整数')
11         if value<0 or value>100:
12             raise ValueError('分数必需在0~100之间')
13         self._score = value
14 
15 s = Student()
16 s.score = 60
17 print(s.score)
18 print('------------------------------')
19 s.score = 999
20 print(s.score)

Python 面向对象编程 随笔 第8张

 

多重继承

给一个类增加多个功能

class Dog(A, B, C):
    pass

 

定制类

非常方便生成特定的类

__str__   

打印自定义的实例

 1 #!/usr/bin/python3
 2 
 3 class Student(object):
 4     def __init__(self, name):
 5         self.name = name
 6     def __str__(self):
 7         return 'Student object (name:%s)' % self.name
 8     __repe__ = __str__
 9 
10 s = Student('Chb')
11 print(s)

Python 面向对象编程 随笔 第9张

 

 __iter__

如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

 1 #!/usr/bin/python3
 2 
 3 class Fib(object):
 4     def __init__(self):
 5         self.a, self.b = 1,1
 6     def __iter__(self):
 7         return self  #实例本身就是迭代对象,故返自己
 8     def __next__(self):
 9         self.a, self.b = self.b, self.a+self.b
10         if self.a > 1000:  #退出循环条件
11             raise StopIteration()
12         return self.a
13         
14 for n in Fib():
15     print(n)

Python 面向对象编程 随笔 第10张

 

 __getitem__

使自己定义的类型和list、dict没什么区别,如可以按索引取值、切片

 1 #!/usr/bin/python3
 2 
 3 class Fib(object):
 4     def __getitem__(self, n):
 5         if isinstance(n, int):  #n是索引的情况
 6             a, b = 1, 1
 7             for x in range(n):
 8                 a, b = b, a+b
 9             return a
10         if isinstance(n, slice):  #n是切片的情况
11             start = n.start
12             stop = n.stop
13             if start is None:  #如果开头没赋值 L[::] 则默认开始下标为0
14                 start = 0
15             a, b = 1, 1
16             L = []
17             for x in range(stop):
18                 if x >= start:
19                     L.append(a)
20                 a, b = b, a+b
21             return L
22         
23 f = Fib()
24 print(f[10])
25 print(f[0:5])

Python 面向对象编程 随笔 第11张

 

__getattr__

正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。

要避免这个错误,可以写一个__getattr__()方法,动态返回一个属性。

 1 #!/usr/bin/python3
 2 
 3 class Student(object):
 4     def __init__(self):
 5         self.name = 'aaa'
 6     def __getattr__(self, attr):
 7         if attr == 'score':
 8             return 60
 9             
10 s = Student()
11 print(s.name)
12 print(s.score)

Python 面向对象编程 随笔 第12张

当调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性,这样,我们就有机会返回score的值

 

__call__

直接对实例进行调用

 1 #!/usr/bin/python3
 2 
 3 class Student(object):
 4     def __init__(self, name):
 5         self.name = name
 6     def __call__(self):
 7         print('My name is %s' % self.name)
 8             
 9 s = Student('chb')
10 print(s())

Python 面向对象编程 随笔 第13张

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄