筱团Blog筱团のBlog

python 面向对象

筱团·2022-07-27 11:15·27 次阅读

python 面向对象

Prerequisite#

如题所示,面向对象
参考文章:廖雪峰

基础面向对象

访问限制#

  • 实例的变量名如果以 __ 开头,就变成了一个私有变量,只有内部可以访问
  • 如果以一个下划线开头的实例变量名,比如 _name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”
  • 类似 __xxx__ 的属性和方法在 Python 中都是有特殊用途的,比如 __len__ 方法返回长度,如果你调用 len() 函数试图获取一个对象的长度,实际上,在 len() 函数内部,它自动去调用该对象的 __len__() 方法
Copy
# 所以,下面的代码是等价的 len('ABC') # 3 'ABC'.__len__() # 3
Copy
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)) student = Student("tuan", "666") # 报错,访问不了私有变量 print(student.__name) print(student.__score) student.print_score() # tuan: 666

如果突然运行外部获取私有变量,可以设置 get_name 函数
如果要更改里面的私有变量,不妨设置 set_name 函数

Copy
def get_name(self): return self.__name def set_score(self, score): if 0 <= score <= 100: self.__score = score else: raise ValueError('bad score')

鸭子类型#

简单的说,就是无论是不是源自同一个父类或者祖父类等,只有它们有相同的函数,那么就是鸭子类型

Copy
class Animal(object): #编写Animal类 def run(self): print("Animal is running...") class Dog(Animal): #Dog类继承Amimal类,没有run方法 pass class Cat(Animal): #Cat类继承Animal类,有自己的run方法 def run(self): print('Cat is running...') pass class Car(object): #Car类不继承,有自己的run方法 def run(self): print('Car is running...') class Stone(object): #Stone类不继承,也没有run方法 pass def run_twice(animal): animal.run() animal.run() print('\n') run_twice(Animal()) run_twice(Dog()) run_twice(Cat()) run_twice(Car()) run_twice(Stone()) """ Animal is running... Animal is running... Animal is running... Animal is running... Cat is running... Cat is running... Car is running... Car is running... # Stone 类就报错了,因为他没有 run 函数 Traceback (most recent call last): File "C:\Users\WPS\Desktop\Temporary\test.py", line 29, in <module> run_twice(Stone()) File "C:\Users\WPS\Desktop\Temporary\test.py", line 21, in run_twice animal.run() AttributeError: 'Stone' object has no attribute 'run' """

实例属性和类属性#

实例属性大于类属性,直接举例

Copy
class Student(object): name = 'Bob' # 类属性 student = Student() print(student.name) # Bob # 添加实例属性 student.name = 'Alice' print(student.name) # Alice # 删除实例属性 del student.name print(student.name) # Bob

高级面向对象

限制实例属性使用 slots#

Copy
class Student(object): __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称 s = Student() # 创建新的实例 s.name = 'Michael' # 绑定属性'name' s.age = 25 # 绑定属性'age' s.score = 99 # 绑定属性'score' # 失败,因为 score 没有被放到__slots__中 class GraduateStudent(Student): pass g = GraduateStudent() g.score = 9999 # 成功,因为__slots__对继承的子类是不起作用的 # 但是如果子类也使用__slots__,那么__slots__不仅对自己起作用,也会继承父类的__slots__

直接调用/修改类属性和只读使用 @property#

Copy
class Student(object): @property # 调用属性 def birth(self): return self._birth @birth.setter # 修改属性 def birth(self, value): self._birth = value @property # 只读 def age(self): return 2015 - self._birth student = Student() student.birth = 2002 # 修改 print(student.birth) # 调用 print(student.age) # 只读

多继承#

原理很简单,就是一个类继承一个主类,再添加额外的功能(额外的类),其实一般的设计思路就是如此

Copy
class Animal(object): pass # 大类: class Mammal(Animal): pass class Bird(Animal): pass # 各种动物: class Dog(Mammal): pass class Bat(Mammal): pass class Parrot(Bird): pass class Ostrich(Bird): pass # 额外的功能 class Runnable(object): def run(self): print('Running...') class Flyable(object): def fly(self): print('Flying...') # 多继承 class Dog(Mammal, Runnable): pass class Bat(Mammal, Flyable): pass

定制类#

这些功能在廖雪峰这篇文章里面,我基本用不到,了解一下即可

  • 调用函数名字(strrepr
  • 类使用 for 循环(iternextgetitem
  • 调用不存在的属性(getattr
  • 链式调用 API(getattr
  • 调用实例自身(call

使用枚举类#

以星期的枚举类举例:

Copy
from enum import Enum, unique @unique class Weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6

使用案例

Copy
>>> day1 = Weekday.Mon >>> print(day1) Weekday.Mon >>> print(Weekday.Tue) Weekday.Tue >>> print(Weekday['Tue']) Weekday.Tue >>> print(Weekday.Tue.value) 2 >>> print(day1 == Weekday.Mon) True >>> print(day1 == Weekday.Tue) False >>> print(Weekday(1)) Weekday.Mon >>> print(day1 == Weekday(1)) True >>> Weekday(7) Traceback (most recent call last): ... ValueError: 7 is not a valid Weekday >>> for name, member in Weekday.__members__.items(): ... print(name, '=>', member) ... Sun => Weekday.Sun Mon => Weekday.Mon Tue => Weekday.Tue Wed => Weekday.Wed Thu => Weekday.Thu Fri => Weekday.Fri Sat => Weekday.Sat

使用元类#

看不懂,略(●'◡'●)

posted @   筱团  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示
目录