‘__’ 双下划线属性
避免属性被外部修改或者被子类覆盖
1 为什么避免外部修改?
因为直接用 : 对象.__属性名称的修改方式会报错
2 为什么避免被子类覆盖?
因为python会将双下划线的属性重命名为’_类名称__属性名字 eg下方例子中的 __age会变为_Person__age
例子
class Person:
def __init__(self, name, age):
self.__name = name # 私有属性:姓名
self.__age = age # 私有属性:年龄
def display_info(self):
print(f"Name: {self.__name}, Age: {self.__age}")
class Employee(Person):
def __init__(self, name, age, emp_id):
super().__init__(name, age)
self.__emp_id = emp_id # 私有属性:员工ID
def display_info(self):
super().display_info()
print(f"Employee ID: {self.__emp_id}")
# 创建 Person 对象
person = Person("Alice", 30)
person.display_info()
# 创建 Employee 对象
emp = Employee("Bob", 25, "E1234")
emp.display_info()
# 尝试直接访问私有属性
print(person.__name) # 将会出现 AttributeError: 'Person' object has no attribute '__name'
print(emp.__emp_id) # 将会出现 AttributeError: 'Employee' object has no attribute '__emp_id'
print(emp._Person__emp_id)
print('类的__age重命名为_Person__age', emp._Person__age) # 输出: _Person__age 25
‘_’ 单下划线属性
把属性定义为一个私有属性 。 单下划线的属性,属于内部实现,外部最好不要调用!
属于君子协定, 用类/对象访问都不会报错
class MyClass:
def __init__(self):
self._private_var = 10
def _private_method(self):
pass
obj = MyClass()
print(obj._private_var) # 输出:10
补充
有时候避免和避免和保留字冲突, 会用 属性后面+单下划线 eg: lambda_=‘2.0’
重载
python没有传统意义的重载,可以用*args 和**kwargs来实现
举例
class Calculator:
def add(self, *args):
if len(args) == 2:
return args[0] + args[1]
elif len(args) == 3:
return args[0] + args[1] + args[2]
else:
return sum(args)
# 创建 Calculator 对象
calc = Calculator()
# 调用不同参数个数的 add 方法
print(calc.add(5, 10)) # 输出:15
print(calc.add(2, 3, 4)) # 输出:9
print(calc.add(1, 2, 3, 4, 5)) # 输出:15
重写
实现和父类相同名字的方法
场景:每个子类都有着一个相同的功能,这个功能则可以放在父类中,子类重写这个方法实现自己的功能特性
举例
class Animal:
def make_sound(self):
print("Animal makes a sound")
class Dog(Animal):
def make_sound(self):
print("Dog barks")
class Cat(Animal):
def make_sound(self):
print("Cat meows")
animal = Animal()
animal.make_sound()
dog = Dog()
dog.make_sound()
cat = Cat()
cat.make_sound()
super()方法
一些需要知道的概念
继承:形式为 一个class(另一个class),括号中的是叫父类,子类可以重写父类的方法
python是如何实现继承?
python会针对每一个类分析出一个mro表:class.mro 得到的一个元祖
然后从左至右的查找待查属性为止 下方的例子中的顺序就是 C->A->B->Base 如果是C.某个方法,那就先从C中找 没有再B中找…找到Base中没有就报错
1 如果子类已经重写了某个方法,那如何再调用父类中的该方法?
super().类方法
一般我们见到super时候都是这样的形式
Class B(A): super().__init__()
# 是为了确保父类能被正确初始化
2 如果子类继承多个父类,那调用super()的顺序是什么?
例子
class Base:
def __init__(self):
print('Initializing Base')
class A(Base):
def __init__(self):
print('Initializing A')
super().__init__()
class B(Base):
def __init__(self):
print('Initializing B')
super().__init__()
class C(A, B):
def __init__(self):
print('Initializing C')
super().__init__()
c = C()
输出
Initializing C
Initializing A
Initializing B
Initializing Base
看一下上面的python是如何实现继承就懂这个输出了