15.面向对象

1. 类的定义

python中的类通过 class 关键字来定义,类的成员有属性方法
# 示例
class ClassName:
<statement-1>
.
.
.
<statement-N>

1.1 属性

类的属性可以显式地定义在类中, 同变量一样,属性的定义必须初始化
class A:
a = 14
b = 12
print(A().a)
# 14
属性还可以隐式地通过构造方法来定义
class A:
# 在构造方法中隐式的定义属性:
def __init__(self):
self.a = 13
self.b = 12
print(A().a)
# 13

1.2 构造方法 _init(self)

Python的构造方法是名为 __init__ 的方法,第一个参数为 self, 指向当前对象。
class A:
def __init__(self,a,b):
self.a = a
self.b = b
print(A(11,12).a)
# 11

1.3 类的方法

类的方法不同于函数,有一个默认参数 self

2. 继承

子类可以继承父类的属性和方法,支持多继承。
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
方法的搜索规则:
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。

2.1 重写方法

  • 在子类中定义与父类相同的方法,就会在子类中重写该方法。
  • 在子类中调用父类方法,需要显示指定父类的名字(可能有多个父类)
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多重继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中参数位置排前父类的方法
强制调用父类的方法:
s = student("Tim",12,180)
super(student,s).speak()
# Tim:12

3. 访问控制

3.1 私有成员

  • 类的私有属性 : __private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs
  • 类的私有方法 : __private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods

4. 专有方法

类的专有方法:
  • __init__ : 构造函数,在生成对象时调用
  • __del__ : 析构函数,释放对象时使用
  • __repr__ : 打印,转换
  • __setitem__ : 按照索引赋值
  • __getitem__: 按照索引获取值
  • __len__ : 获得长度
  • __cmp__ : 比较运算
  • __call__ : 函数调用
  • __add__ : 加运算
  • __sub__ : 减运算
  • __mul__ : 乘运算
  • __truediv__ : 除运算
  • __mod__ : 求余运算
  • __pow__ : 乘方
class object:
__doc__: str | None
__dict__: dict[str, Any]
__module__: str
__annotations__: dict[str, Any]
@property
def __class__(self: Self) -> type[Self]: ...
# Ignore errors about type mismatch between property getter and setter
@__class__.setter
def __class__(self, __type: type[object]) -> None: ... # type: ignore # noqa: F811
def __init__(self) -> None: ...
def __new__(cls: type[Self]) -> Self: ...
# N.B. `object.__setattr__` and `object.__delattr__` are heavily special-cased by type checkers.
# Overriding them in subclasses has different semantics, even if the override has an identical signature.
def __setattr__(self, __name: str, __value: Any) -> None: ...
def __delattr__(self, __name: str) -> None: ...
def __eq__(self, __o: object) -> bool: ...
def __ne__(self, __o: object) -> bool: ...
def __str__(self) -> str: ... # noqa Y029
def __repr__(self) -> str: ... # noqa Y029
def __hash__(self) -> int: ...
def __format__(self, __format_spec: str) -> str: ...
def __getattribute__(self, __name: str) -> Any: ...
def __sizeof__(self) -> int: ...
# return type of pickle methods is rather hard to express in the current type system
# see #6661 and https://docs.python.org/3/library/pickle.html#object.__reduce__
def __reduce__(self) -> str | tuple[Any, ...]: ...
if sys.version_info >= (3, 8):
def __reduce_ex__(self, __protocol: SupportsIndex) -> str | tuple[Any, ...]: ...
else:
def __reduce_ex__(self, __protocol: int) -> str | tuple[Any, ...]: ...
def __dir__(self) -> Iterable[str]: ...
def __init_subclass__(cls) -> None: ...