「Python 基础」面向对象编程
创始人
2024-05-29 22:19:30
0

文章目录

    • 1. 面向对象编程
      • 类和实例
      • 访问限制
      • 继承和多态
      • type()
      • isinstance()
      • dir()
      • 实例属性和类属性
    • 2. 面向对象高级编程
      • \_\_slots\_\_
      • @property
      • 多重继承
      • 定制类
      • 枚举类
      • 元类

1. 面向对象编程

Object Oriented Programming

简称 OOP,一种程序设计思想,以对象为程序基本单元,一个对象包含数据和数据的操作方法;

面向对象的设计思想来自自然界的类(Class)和实例(Instance),抽象出 Class,根据 Class 创建 Instance,抽象程度比函数高(既包含数据,又包含操作数据的函数);

数据封装、继承、多态是面向对象的三大特点;

类和实例

Class 是抽象的模板,是创建 Instance 的模板;

>>> class Student(object): # 定义类
...     pass
...
>>> s1 = Student() # 创建实例
>>> s1.name = 'Aurelius' # 实例属性绑定
>>> s1.name
'Aurelius'

Python 允许对实例绑定任何数据,即使一个类的两个实例,他们拥有的变量名称都可能不同;

创建实例时强制绑定属性;

class Student(object):def __init__(self, name, score):self.name = nameself.score = score

和普通函数相比,类中定义的函数第一个参数永远是实例变量 self,且调用时不用传值,self 指向创建的实例本身

数据封装

通过实例函数访问实例的数据,不直接从外部访问这些数据;

访问限制

限制外部代码对实例内部一些属性和方法的访问,可以加强代码的健壮性;

Python 没有任何强制机制限制访问权限;

在 Class 定义的内部属性前加 __ 可以把属性变成私有,通过 get_p(), set_p() 方法来访问这些属性;

__property 被 Python 解释器自动改为 _ClassName__property

__xxx__ 在 Python 中属于特殊属性,不是私有的,可以被访问的;

继承和多态

  • 继承,可以把父类的所有功能直接拿来,子类只需要新增自己特有的方法,重写覆盖父类中不适合的方法;

  • 多态,是把一个子类对象赋给一个父类变量,调用方法是子类实现;

开闭原则

对扩展开放,对修改封闭;

鸭子模式

def twice_run(animal):animal.run()animal.run()class Timer(object):def run(self):print('Start ...')

传入 twice_run() 的对象不必是 Animal 的子类,只要有 run() 即可;

因此相对静态语言,动态语言(Python)的继承不是那么必要;

type()

获取对象类型;

类型类型常量对象
intint123
strstr‘123’
函数types.FunctionTypedef fn(): pass
内建函数types.BuiltinFunctionTypeabs
匿名函数types.LambdaTypelambda x: x
生成器types.GeneratorType(x for x in range(10))

isinstance()

判断是否指定类型或指定类型元组中的一个;

>>> isinstance(x, t) # x 是对象,t 是类型,t 可以是多个类型组成的一个 tuple 对象

dir()

获取对象的所有属性和方法;

len()

实际是调用了对象的 __len__() 方法,因此按照鸭子类型,自己的类只要实现了 __len__(),也可以使用 len(myObj);

getattr(obj, pname)

获取对象的指定属性或方法,也可以传第 3 个参数作为默认值;

setattr(obj, pname, pvalue)

设置对象指定属性的值;

hasattr(obj, pname)

判断对象是否存在指定名称的属性或方法;

可以确定存在而直接访问的属性或方法,就不要使用getattr,因此可以通过hasattr判断属性或方法是否存在;

实例属性和类属性

通过实例变量或self变量绑定实例属性

通过类本身绑定的是类属性,类属性归类所有,但类的所有实例都可以访问到;

>>> class Student(object):
...     name = 'Student'
...
>>> s = Student()
>>> print(s.name)
Student
>>> print(Student.name)
Student
>>> s.name = 'Aurelius'
>>> print(s.name)
Aurelius
>>> print(Student.name)
Student
>>> del s.name
>>> print(s.name)
Student

相同名称的实例属性将屏蔽类属性(当查找到对应名称的实例属性时,即使存在同名类属性,也不会被查找到),当删除实例属性后,可以再次访问到类属性;

2. 面向对象高级编程

__slots__

动态绑定方法

Instance绑定方法,只对当前Instance有效;

class Student(object):passs = Student()def set_age(self, age):self.age = agefrom types import MethodType
s.set_age = MethodType(set_age, s)
s.set_age(25)

Class绑定方法,对所有Instance有效;

def set_score(self, score):self.score = scoreStudent.set_score = set_score
s.set_score(100)

使用 __slots__

用来限制 class 实例可以添加的属性,包括Class定义中绑定的属性;

class Student(object):# tuple定义允许绑定的属性名称__slots__ = ('name', 'age')

__slots__只对当前类有效,对子类无效;若子类也定义了__slots__,有效范围是自身加父类的范围;

不定义__slots__的类相当于其有效范围是任意属性;

@property

把一个getter方法变成属性,同时创建另一个装饰器@pname.setter,负责把另一个setter方法变成属性赋值;

class Student(object):@propertydef birth(self):return self._birth@birth.setterdef birth(self, value):self._birth = value# 只读属性@propertydef age(self):return 2020 - self._birth

多重继承

Python 允许使用多重继承,一个子类可以同时继承多个父类的所有功能;

MixIn

除了继承自主线,还额外混入其他类的功能,这种设计叫MixIn

定制类

通过一些__xxx__属性定制类;

__str__

返回给用户看到的字符串,实例的打印结果;

__repr__

返回实例调式值显示结果;

__iter__

Class实例变成一个迭代器,需要实现__next__()方法,for 循环会不断调用迭代对象的__next__()

class Fib(object):def __init__(self):self.a, self.b = 0, 1def __iter__(self):return selfdef __next__(self):self.a, self.b = self.b, self.a + self.bif self.a > 1000:raise StopIteration()return self.a

__getitem__

通过索引器或者切片读取实例的值时被调用;

class Fib(object):def __getitem__(self, n):if isinstance(n, int):a, b = 1, 1for x in range(n):a, b = b, a + breturn aif isinstance(n, slice):start, stop = n.start, n.stopif start is None:start = 0a, b = 1, 1res = []for x in range(stop):if x >= start:res.append(a)a, b = b, a + breturn res

slicestep参数和负数值可以进一步处理

__getattr__

当调用实例不存在的属性时被调用,已有的属性不会在__getattr__中查找;

__getattr__可以实现完全动态的调用

class Chain(object):def __init__(self, path=''):self._path = pathdef __getattr__(self, path):return Chain(f'{self._path}/{path}')def __call__(self, param):return Chain(f'{self._path}/{param}')def __str__(self):return self._path__repr__ = __str__print(Chain().status.user('Aurelius').timeline.list)

__call__

定义了__call__,就可以调用实例本身,__call__可以有参数;

class Student(object):def __init__(self, name):return self._namedef __call__(self, text):print(f'{self._name}: {text}')print(Student('Aurelius')('A'))

类本身的调用会执行type__call__方法

枚举类

将一组相关常量定义在一个Class中,并且不可变,成员可以直接比较;

通过Enum调用

>>> from enum import Enum
>>> Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
>>> for name, member in Month.__members__.items():
...    print(name, '=>', member, ',', member.value)
...
Jan => Month.Jan , 1
Feb => Month.Feb , 2
Mar => Month.Mar , 3
Apr => Month.Apr , 4
May => Month.May , 5
Jun => Month.Jun , 6
Jul => Month.Jul , 7
Aug => Month.Aug , 8
Sep => Month.Sep , 9
Oct => Month.Oct , 10
Nov => Month.Nov , 11
Dec => Month.Dec , 12

通过继承Enum

from enum import Enum, unique@unique
class Weekday(Enum):Sum = 0 # 默认从 1 开始,这里设置 0Mon = 1Tue = 2Wed = 3Thu = 4Fri = 5Sat = 6

获取方式

  • Enum['Name']
  • Enum.Name
  • Enum(value)

元类

type

type函数既可以返回一个对象的类型,又可以创建出新的类型;

type创建class

def fn(self, name='world'):print(f'Hello, {name}')Hello = type('Hello', (object,), dict(hello=fn))
h = Hello()
h.hello()

type() 的 3 个参数:

  • class 的名称
  • 继承的父类元组
  • class 的方法和其绑定函数的字典

metaclass

metaclass允许创建类或修改类,可以把类看作metaclass创建的实例;

定义metaclass

class ListMetaclass(type):def __new__(cls, name, bases, attrs):attrs['add'] = lambda self, value: self.append(value)return type.__new__(cls, name, bases, attrs)

__new__()的 4 个参数依次是:

  • 当前准备创建的类对象
  • 类的名称
  • 类继承的父类元组
  • 类的方法字典

定制类

# 在 Python 解释器创建 MyList 时,要通过 ListMetaclass.__new__() 来创建
class MyList(list, metaclass=ListMetaclass):pass

Python 解释器首先在当前类的定义中查找metaclass,如果没有,就继续在父类查找,知道找到,用来创建当前类,metaclass隐式继承到子类;


上一篇:「Python 基础」函数与高阶函数
专栏:《Python 基础》

PS:感谢每一位志同道合者的阅读,欢迎关注、评论、赞!

相关内容

热门资讯

这些日常用语竟都源自戏曲 转自:贵州日报京剧《穆桂英挂帅》剧照。 新华/传真 戏曲文化以其独特的魅力深深吸引着...
美国得州洪水死亡人数升至80人 转自:贵州日报 新华社休斯敦7月6日电 美国得克萨斯州政府和地方政府6日说,截至当天下午,得...
第三家股份行AIC来了 招银金... 每经记者 赵景致 每经编辑 陈 星  近日,招商银行发布公告称,已收到《国家金融监督管理总局关于筹建...
求男主男友力爆棚的小说,不要太... 求男主男友力爆棚的小说,不要太玛丽苏,多一点哦宦妃天下?纨绔世子妃?
求古代小说名和男女主名,女主名... 求古代小说名和男女主名,女主名字里要有个嫣字,内容是两个会武功的求古代小说名和男女主名,女主名字里要...
谁有资格被称为“进攻万花筒”呢... 谁有资格被称为“进攻万花筒”呢?安东尼,皮尔斯,杜兰特,科比,麦迪,艾弗森,乔丹,哈登。安东尼有资格...
四川国光农化股份有限公司关于使... 证券代码:002749 证券简称:国光股份 公告编号:2025-042号四川国光农化股份有限公司关...
最近什么书好看 最近什么书好看最近好像书慌啊!感觉没什么好书!大家给我推荐个!最好是年前刚写的或今年写的!要不我感觉...
莫要遇事躲着走 ●荣庐 鸵鸟一遇到危险,就会把头埋入沙中自以为安全。而在现实中,有的干部就如鸵鸟一般,见事儿就...
上海城地香江数据科技股份有限公... 证券简称:城地香江 证券代码:603887 公告编号:2025-079上海城地香江数据科技股份有限...