注意 py 中声明只有一个元素的元组的时候应该写成 t = (1,)
而不是 (1)
。后者会被解释器解释为变量而非元组。
多继承
和 java 有着显著区别,python3 的类允许多继承。多继承带来了菱形问题(Diamond Problem):如果多个父类继承同一个基类,可能导致方法调用冲突。如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class A: def method(self): print("A")
class B(A): def method(self): super().method() print("B")
class C(A): def method(self): super().method() print("C")
class D(B, C): def method(self): super().method() print("D")
d = D() d.method() print(D.__mro__)
|
Python 3 使用 C3 线性化算法(MRO)解决冲突。在上面的例子中:
- 调用顺序:D → B → C → A(B 优先于 C,因为 class D(B, C) 里 B 在前)。
- 如果 B 没有 method(),则调用 C 的 method()。
上面的例子中 A 虽然被继承了 2 次,但是并不存在调用多次的问题。
多继承可以很方便实现 mix-in 模式。
slots
__slots__
的目的是限制当前类所能拥有的属性,避免因为外部属性的操作导致类属性越来越难以管理。
1 2 3 4 5 6 7 8 9
| class Student(object): __slots__ = ('name', 'gender', 'score') def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = score
s = Student('Bob', 'male', 59)
|
call
__call__
方法可以让一个类的实例像函数一样被调用。当实例后面加括号时,就会调用 __call__
方法。
1 2 3 4 5 6 7 8 9 10 11
| class Fib: def __call__(self, count = 10): res = [] a, b = 0, 1 for i in range(count): res.append(a) a, b = b, a + b return res
f = Fib() print(f(10))
|
函数式编程
可以实现延迟计算:
1 2 3 4
| def calc_sum(list_): def lazy_sum(): return sum(list_) return lazy_sum
|
装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import time
def performance(unit): def perf_decorator(f): def wrapper(*args, **kwargs): t1 = time.time() r = f(*args, **kwargs) t2 = time.time() t = (t2 - t1) * 1000 if unit == 'ms' else (t2 - t1) print('call {}() in {} {}'.format(f.__name__, t, unit)) return r return wrapper return perf_decorator
@performance('ms')
def test(a): time.sleep(1) print('test', a)
test(1)
|