doc: 阅读python面向对象文档

This commit is contained in:
asahi
2025-08-18 23:57:01 +08:00
parent 3f20f381a8
commit ab6898d7eb

View File

@@ -103,6 +103,23 @@
- [global](#global) - [global](#global)
- [nonlocal](#nonlocal) - [nonlocal](#nonlocal)
- [global namespace](#global-namespace) - [global namespace](#global-namespace)
- [Class Objects](#class-objects)
- [__init__](#init)
- [data attributes](#data-attributes)
- [method object](#method-object)
- [class and instance variables](#class-and-instance-variables)
- [function object](#function-object)
- [Inheritance](#inheritance)
- [attribute resolving](#attribute-resolving)
- [method resolving](#method-resolving)
- [built-in functions](#built-in-functions)
- [private variables](#private-variables)
- [name mangling](#name-mangling)
- [odds and ends](#odds-and-ends)
- [`__self__, __func__`](#__self__--__func__)
- [iterators](#iterators)
- [generators](#generators)
- [generator expression](#generator-expression)
# Python # Python
@@ -1691,3 +1708,330 @@ After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam After global assignment: nonlocal spam
In global scope: global spam In global scope: global spam
``` ```
### Class Objects
class对象支持两种类型的操作`attribute reference`和`instantiation`。
attribute reference使用`obj.name`的语法。class定义如下:
```py
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
```
`MyClass.i`和`MyClass.f`是有效的attribute reference会返回一个integer和一个function。
`__doc__`也是一个有效的attribute返回对该class的简单文档描述。
类实例化类似于函数的调用,其语法如下:
```py
x = MyClass()
```
上述示例会创建一个MyClass类型的对象并且将其赋值给本地变量x。
#### __init__
python中支持在初始化时为对象指定状态故而可以自定义构造器示例如下
```py
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
c = Complex(3.0, -4.5)
```
#### data attributes
python中的data attributes类似于c++中的data members但是`data attributes`并不需要被声明其类似于local variables其在第一次赋值时就存在了。
例如,`变量x是MyClass类的实例`,那么如下代码将会输出`16`.
#### method object
除了通过data attribute外另一种attribute reference的方式是method。
在python中class中的function定义了object中的method。但是`x.f`和`MyClass.f`并不等价前者是method object后者是function object。
通常method在其所绑定的对象后调用
```py
x.f()
```
python中`x.f`为一个method object支持被存储在变量中并可以在后续通过变量调用示例如下
```py
xf = x.f
while True:
print(xf())
```
如上所示method object `x.f`被存储在local variable `xf`中后,后续可以通过`xf()`来调用method object。
> 按照`MyClass`的类定义,`x.f`方法将会接收一个`self`参数,但是在调用`xf()`时,并没有传递任何参数。
实际上对于method而言其method所绑定的对象实例将会作为参数被传向function的第一个参数`self`。
故而对于method object和function object而言`x.f()`实际上等价于`MyClass.f(x)`。
对于method object而言`obj.method(arg1, arg2 ...)`的调用等价于`Class.method(obj, arg1, arg2 ...)`的function调用。
### class and instance variables
简单来说每个对象的instance variables是相互独立的但是class variables则是在同一类的所有对象间都是共享的。
```py
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
```
对于class variables而言其既可以通过`MyClass.name`来进行访问,也可以通过`obj.name`来进行访问。
但是在class variable和instance variable同名时instance variable会优先被访问示例如下
```py
class Warehouse:
purpose = 'storage'
region = 'west'
w1 = Warehouse()
print(w1.purpose, w1.region)
storage west
w2 = Warehouse()
w2.region = 'east'
print(w2.purpose, w2.region)
storage east
```
在python中用户既可以通过method来访问data attributes也可以通过对象直接访问。并且python中也没有类似其他语言中`private`这类强制隐藏的机制,`python中都是基于约定`。
在使用data attributes时应当小心如下场景
- data attributes可能被method维护和管理若用户不经过method直接修改attribute的值可能会造成attribute的状态被破坏没有经过method中的相关校验直接将attribute改为错误值
- 用户可以在`避免命名冲突`的前提下向data attributes添加自己的值
在python中对象中method的第一个参数名为`self`,这只是一个约定,`self`在python中并没有特别的意义。
#### function object
python中function object为一个class attribute用于定义method。function object并不一定要定义在class内部示例如下
```py
# Function defined outside the class
def f1(self, x, y):
return min(x, x+y)
class C:
f = f1
def g(self):
return 'hello world'
h = g
```
在上述示例中,类`C`包含`f, g, h`三个attributesC实例中也包含`f, g, h`三个method。其中`h`和`g`完全等价。
在python的class定义中method可以通过`self.xxx`调用其他method示例如下
```py
class Bag:
def __init__(self):
self.data = []
def add(self, x):
self.data.append(x)
def addtwice(self, x):
self.add(x)
self.add(x)
```
method中同样可以访问global namesmethod关联的global scope是method定义所位于的module。
> 在python中每个值都是一个对象其class信息存储在`object.__class__`中。
### Inheritance
在python中支持类的继承示例如下
```py
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
```
#### attribute resolving
若派生类B继承了基类A那么在对B的对象进行attribute解析时其首先会查找派生类如果在派生类中没有找到则会继续在基类中查找。
#### method resolving
method解析也会从派生类开始沿着基类逐渐查询直到找到对应的function object。
在python中派生类的方法会覆盖基类的方法用c++中的概念来理解即python中所有的method都是virtual的。
在python中如果派生类方法中想要调用基类的方法可以通过`BaseClassName.methodname(self, arguments)`,其类似于其他语言中的`super`。
#### built-in functions
python中包含如下built-in function来判断继承关系
- `isinstance`: 该方法通常用于检查是否实例属于某一个类
- `isinstance(obj, int)`
- `issubclass`: 该方法通常用于检查是否一个类派生自另一个类
- `issubclass(bool, int)`: 该调用返回为Truebool是int的子类
### private variables
python中并不存在只能从类内部访问的`private instance variable`。但是python编码中存在一个规范约束
- 以`_`开头的名称应当被作为api中的非公开部分下划线开头的可以是function, method, data member
#### name mangling
在类定义中,任何以`__spam`定义的name至少两个前缀下划线最多一个后缀下划线都会被替换为`_classname__spam`的形式。
name magling在不破坏列内部调用的场景下十分有用示例如下
```py
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)
def update(self, iterable):
for item in iterable:
self.items_list.append(item)
__update = update # private copy of original update() method
class MappingSubclass(Mapping):
def update(self, keys, values):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)
```
在上述代码中,即使在`MappingSubclass`中引入`__update`,其名称也为`_MappingSubclass__update`,和`_Mapping__update`不同,仍然不会对父类造成影响。
在类中以`__spam`定义的变量,在类外部可以以`_classname__spam`进行访问。
### odds and ends
有时想使用类似C语言中的struct惯用方法是使用`dataclasses`,示例如下所示:
```py
from dataclasses import dataclass
@dataclass
class Employee:
name: str
dept: str
salary: int
```
```py
>>> john = Employee('john', 'computer lab', 1000)
>>> john.dept
'computer lab'
>>> john.salary
1000
```
### `__self__, __func__`
instance method object拥有如下属性
- `__self__`: `m.__self__`代表method m关联的实例对象
- `__func__`: `m.__func__`代表method关联的function object
### iterators
在python中大多数容器对象都可以通过for-statements进行迭代
```py
for element in [1, 2, 3]:
print(element)
for element in (1, 2, 3):
print(element)
for key in {'one':1, 'two':2}:
print(key)
for char in "123":
print(char)
for line in open("myfile.txt"):
print(line, end='')
```
在底层for-statement针对容器对象调用了`iter()`方法,该方法会返回一个`iterator`对象iterator对象中定义了`__next__()`方法,该方法在终止时会抛出`StopIteration`异常。
可以通过内置的`next()`方法来调用`__next__()`,示例如下所示:
```py
>>> s = 'abc'
>>> it = iter(s)
>>> it
<str_iterator object at 0x10c90e650>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration
```
如果想要为自定义类添加iterator可以在类中定义一个`__iter__()`方法,该方法返回一个带`__next__()`方法的对象。`如果一个class中包含了__next__()方法的定义那么__iter__()方法仅需返回self即可`。
```py
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
```
### generators
`Generators`可以简单的创建iterator其编写和函数类似但是当想要返回值时使用`yield statement`。
每次调用`next()`时generator都会从上次中止的地方进行恢复。示例如下所示
```py
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
```
```py
>>> for char in reverse('golf'):
print(char)
f
l
o
g
```
通过generator完成的任何事情都可以通过iterator来完成但是generator的代码更加紧凑其`__iter__`和`__next__`方法都是自动生成的。
在generator的多次next调用之间local variables的状态和执行状态也是自动保存的。
generator令iterator的编写更加简单。
### generator expression
一些简单的迭代器可以简化为表达式:
```py
>>> sum(i*i for i in range(10)) # sum of squares
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product
260
>>> unique_words = set(word for line in page >>> for word in line.split())
>>> valedictorian = max((student.gpa, student.name) for student in graduates)
>>> data = 'golf'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']
```