Vì thứ tự độ phân giải phương thức là
[__main__.C, __main__.A, __main__.B, object]
, thay vào đó,class B
có thể được xác định theo cách sau không?
Không, bởi vì sau đó điều này sẽ thất bại:
class D:
def __init__[self, d, **kwargs]:
self.d = d
super[].__init__[**kwargs]
class E[C, D]:
def __init__[self, e, **kwargs]:
self.e = e
super[].__init__[**kwargs]
MRO của E
là [E, C, A, B, D, object]
, vì vậy
class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
0 phải gọi class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
1 nếu không class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
2 sẽ không được gọi.Không phải
3 trongclass RightPyramid[Triangle, Square]: def __init__[self, base, slant_height]: self.base = base self.slant_height = slant_height def what_am_i[self]: return 'RightPyramid'
class B
dư thừa, vì bất kỳ thặng dư nào5 được chuyển choclass RightPyramid[Triangle, Square]: def __init__[self, base, slant_height]: self.base = base self.slant_height = slant_height def what_am_i[self]: return 'RightPyramid'
6 sẽ được chuyển choclass RightPyramid[Triangle, Square]: def __init__[self, base, slant_height]: self.base = base self.slant_height = slant_height def what_am_i[self]: return 'RightPyramid'
7, tăng?class RightPyramid[Triangle, Square]: def __init__[self, base, slant_height]: self.base = base self.slant_height = slant_height def what_am_i[self]: return 'RightPyramid'
Không, vì thặng dư
class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
5 sẽ được chuyển đến class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
2 trong ví dụ trên. Nhưng ngay cả khi không có điều đó, việc nêu ra lỗi khi bạn gọi một hàm tạo có quá nhiều đối số; Rất mong muốn có một thông báo lỗi thông báo cho bạn về mã không chính xác của bạn, thay vì sai lầm không bị phát hiện.Đây có phải là một biện pháp bảo vệ nếu
6 được xác định làclass RightPyramid[Triangle, Square]: def __init__[self, base, slant_height]: self.base = base self.slant_height = slant_height def what_am_i[self]: return 'RightPyramid'
1 thay vìclass A: def __init__[self]: print['A'] super[].__init__[] class B[A]: def __init__[self]: print['B'] super[].__init__[] class X: def __init__[self]: print['X'] super[].__init__[] class Forward[B, X]: def __init__[self]: print['Forward'] super[].__init__[] class Backward[X, B]: def __init__[self]: print['Backward'] super[].__init__[]
2?class A: def __init__[self]: print['A'] super[].__init__[] class B[A]: def __init__[self]: print['B'] super[].__init__[] class X: def __init__[self]: print['X'] super[].__init__[] class Forward[B, X]: def __init__[self]: print['Forward'] super[].__init__[] class Backward[X, B]: def __init__[self]: print['Backward'] super[].__init__[]
Trong một số ý nghĩa, chắc chắn; Nhưng thực sự đó là một biện pháp bảo vệ cho
class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
0 xảy ra trong bất kỳ hệ thống phân cấp lớp nào, miễn là các lớp khác trong hệ thống phân cấp tuân theo cùng một quy tắc gọi class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
3. Python hỗ trợ kế thừa từ nhiều lớp. Trong bài học này, bạn sẽ thấy:inheritance from multiple classes. In this lesson, you’ll see:
- Cách thức hoạt động của nhiều kế thừa
- Cách sử dụng
5 để gọi các phương thức được kế thừa từ nhiều phụ huynhclass A: def __init__[self]: print['A'] super[].__init__[] class B[A]: def __init__[self]: print['B'] super[].__init__[] class X: def __init__[self]: print['X'] super[].__init__[] class Forward[B, X]: def __init__[self]: print['Forward'] super[].__init__[] class Backward[X, B]: def __init__[self]: print['Backward'] super[].__init__[]
- Sự phức tạp nào xuất phát từ nhiều kế thừa
- Cách viết mixin, là cách sử dụng phổ biến của nhiều kế thừa
Một lớp học có thể thừa hưởng từ nhiều phụ huynh.Ví dụ: bạn có thể xây dựng một lớp đại diện cho hình dạng 3D bằng cách kế thừa từ hai hình 2D:
class RightPyramid[Triangle, Square]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
def what_am_i[self]:
return 'RightPyramid'
Thứ tự phân giải phương pháp [MRO] xác định nơi Python tìm kiếm một phương thức khi có hệ thống phân cấp các lớp.Sử dụng
class A:
def __init__[self]:
print['A']
super[].__init__[]
class B[A]:
def __init__[self]:
print['B']
super[].__init__[]
class X:
def __init__[self]:
print['X']
super[].__init__[]
class Forward[B, X]:
def __init__[self]:
print['Forward']
super[].__init__[]
class Backward[X, B]:
def __init__[self]:
print['Backward']
super[].__init__[]
5 truy cập lớp tiếp theo trong MRO:Method Resolution Order [MRO] determines where Python looks for a method when there is a hierarchy of classes. Using class A:
def __init__[self]:
print['A']
super[].__init__[]
class B[A]:
def __init__[self]:
print['B']
super[].__init__[]
class X:
def __init__[self]:
print['X']
super[].__init__[]
class Forward[B, X]:
def __init__[self]:
print['Forward']
super[].__init__[]
class Backward[X, B]:
def __init__[self]:
print['Backward']
super[].__init__[]
5 accesses the next class in the MRO:class A:
def __init__[self]:
print['A']
super[].__init__[]
class B[A]:
def __init__[self]:
print['B']
super[].__init__[]
class X:
def __init__[self]:
print['X']
super[].__init__[]
class Forward[B, X]:
def __init__[self]:
print['Forward']
super[].__init__[]
class Backward[X, B]:
def __init__[self]:
print['Backward']
super[].__init__[]
Nếu bạn kết hợp tính năng MRO và
class A:
def __init__[self]:
print['A']
super[].__init__[]
class B[A]:
def __init__[self]:
print['B']
super[].__init__[]
class X:
def __init__[self]:
print['X']
super[].__init__[]
class Forward[B, X]:
def __init__[self]:
print['Forward']
super[].__init__[]
class Backward[X, B]:
def __init__[self]:
print['Backward']
super[].__init__[]
7 để chỉ định các cặp giá trị tên trong quá trình xây dựng, bạn có thể viết mã chuyển các tham số cho các lớp cha ngay cả khi chúng có tên khác nhau:class A:
def __init__[self]:
print['A']
super[].__init__[]
class B[A]:
def __init__[self]:
print['B']
super[].__init__[]
class X:
def __init__[self]:
print['X']
super[].__init__[]
class Forward[B, X]:
def __init__[self]:
print['Forward']
super[].__init__[]
class Backward[X, B]:
def __init__[self]:
print['Backward']
super[].__init__[]
7 feature for specifying name-value pairs during construction, you can write code that passes parameters to parent classes
even if they have different names:class Rectangle:
def __init__[self, length, width, **kwargs]:
self.length = length
self.width = width
super[].__init__[**kwargs]
def area[self]:
return self.length * self.width
def perimeter[self]:
return 2 * self.length + 2 * self.width
class Square[Rectangle]:
def __init__[self, length, **kwargs]:
super[].__init__[length=length, width=length, **kwargs]
class Triangle:
def __init__[self, base, height, **kwargs]:
self.base = base
self.height = height
super[].__init__[**kwargs]
def tri_area[self]:
return 0.5 * self.base * self.height
class RightPyramid[Square, Triangle]:
def __init__[self, base, slant_height, **kwargs]:
self.base = base
self.slant_height = slant_height
kwargs["height"] = slant_height
kwargs["length"] = base
super[].__init__[base=base, **kwargs]
def area[self]:
base_area = super[].area[]
perimeter = super[].perimeter[]
return 0.5 * perimeter * self.slant_height + base_area
def area_2[self]:
base_area = super[].area[]
triangle_area = super[].tri_area[]
return triangle_area * 4 + base_area
Nhiều kế thừa có thể trở nên khó khăn nhanh chóng.Một trường hợp sử dụng đơn giản là phổ biến trong trường là viết một mixin.Một mixin là một lớp không quan tâm đến vị trí của nó trong hệ thống phân cấp, nhưng chỉ cung cấp một hoặc nhiều phương pháp tiện lợi:mixin. A mixin is a class that doesn’t care about its position in the hierarchy, but just provides one or more convenience methods:
class SurfaceAreaMixin:
def surface_area[self]:
surface_area = 0
for surface in self.surfaces:
surface_area += surface.area[self]
return surface_area
class Cube[Square, SurfaceAreaMixin]:
def __init__[self, length]:
super[].__init__[length]
self.surfaces = [Square, Square, Square, Square, Square, Square]
class RightPyramid[Square, Triangle, SurfaceAreaMixin]:
def __init__[self, base, slant_height]:
self.base = base
self.slant_height = slant_height
self.height = slant_height
self.length = base
self.width = base
self.surfaces = [Square, Triangle, Triangle, Triangle, Triangle]
Đây là những gì bạn nhận được:
>>>
>>> cube = Cube[3]
>>> cube.surface_area[]
54