python 面向对象 对象 继承

张开发
2026/5/30 13:26:53 15 分钟阅读
python 面向对象 对象 继承
类构造函数# 创建类classStudent:nameNone# 成员属性ageNone# 成员属性defsay(self):# 成员方法print(self.name)# 构造函数def__init__(self,name,age):self.namename self.ageage#创建类对象my_studentStudent()# 对象的属性 赋值my_student.nameZENmy_student.age20#也可以追加属性my_student.xxxvvvv# 获取对象的信息my_student.say()# 自动执行构造函数__init__,给属性初始化my_student1Stuendt(Ares-Wang,200)# 打印实例所有属性、方法print(my_student1.__dict__)魔术方法python中类中有内置方法这些内置方法成为魔术方法dictmro:用于记录属性核方法的查找顺序魔术方法如下[常用]init构造函数 自动执行str字符串方法lt小于、大于符号比较le小于等于、大于等于符号比较eq等于符号实例.dict》对象身上自己的东西dir(实例) 》对象可以访问的东西自己的、继承过来的面向对象的特点封装多态继承##python中私有属性、私有方法跟C# 私有成员访问控制一样的private实例对象无法访问但类内部可以放在这些私有成员的classBase:def__init__(self):self._protected_var10# 受保护属性def_protected_method(self):# 受保护方法print(这是一个受保护的方法)classSubClass(Base):defaccess_protected(self):print(self._protected_var)# ✅ 子类可以访问 self._protected_method()# ✅ 子类可以调用 objSubClass()print(obj._protected_var)# ⚠️ 外部可以访问但 IDE 可能会警告classMyClass:def__init__(self):self.__private_var42# 私有属性 self.public_var100def__private_method(self):# 私有方法return这是私有方法defpublic_method(self):# 内部可以访问print(self.__private_var)print(self.__private_method())classSubClass(MyClass):deftry_access(self):# ❌ 下面这行会报错因为 __private_var 在子类中不存在# print(self.__private_var)# ✅ 但可以通过改名后的名字访问虽然不建议这么做print(self._MyClass__private_var)# 输出42objMyClass()obj.public_method()# ✅ 正常工作# ❌ 外部直接访问会报错# print(obj.__private_var) # AttributeError# ✅ 但仍然可以通过改名后的名字强制访问掘地三尺print(obj._MyClass__private_var)# 输出42getter setterclassAnimal:def__init__(self,name,age,yun_qi):self.namename # 公共属性publicself._ageage # 受保护属性protectedpropertydefage(self):returnself._age age.setterdefage(self,age):self._ageageaAnimal(狗,1岁,6月)print(a.age)a.age3岁print(a.age)classPerson:def__init__(self,age):self._ageage # 实际存在的是 _age propertydefage(self):getter把方法变成属性来用returnself._age age.setterdefage(self,value):setter当给 age 赋值时调用ifnotisinstance(value,(int,float)):raiseValueError(年龄必须是数字)ifvalue0orvalue150:raiseValueError(年龄必须在0-150之间)self._agevalue# 使用pPerson(20)print(p.age)#20像访问属性一样不用加括号 p.age25# ✅ 赋值时会自动调用setterprint(p.age)#25# p.age -5 # ❌ 报错年龄必须在0-150之间property 把age()方法变成了 getter age.setter 把另一个同名方法变成了 setter 外部代码感觉不到这是方法调用就像在直接读写属性继承classclassA:# classB类 继承classA类 单继承classclassB(classA):# 多继承 同名的成员属性、成员方法按继承的顺序左边的优先级高# pass 占位符保证语法完整让语法不报错表示无内容空class类名(父类1,父类2,父类3,.....父类N)passclassParent:def__init__(self,name):self.namenameclassChild(Parent):def__init__(self,name,age):super().__init__(name)# 调用父类的 __init__传递 name 参数self.ageage cChild(小明,10)print(c.name,c.age)# 小明 10重写 跟C# override 重写 效果一样{override 重写父类的virtual}但理解比C# 更方便classFather:name父类defsay(self):return我是父类classSub(Father):# name 子类defsay(self):print(super().say())# print(Father.say(self)) 通过父类.方法(self) 调用父类方法# print(super().name) 如果Sub类的name 不注释掉注释掉都调用父类的name 属性 打印 父类# print(Father.name) 如果Sub类的name 不注释掉注释掉都调用父类的name 属性 打印 父类# print(self.name) 如果Sub类的name不注释 则调用Sub的name 打印 子类return我是子类my_subSub()print(my_sub.name)# 因Sub类 注释了 name 子类 所以此处打印 父类如果取消注释则打印 子类print(my_sub.say())# 调用Sub类的say方法 因方法通过super().say() 调用父类的say方法所以打印 我是父类 我是子类类型注解变量的类型注解 加个 类型语法格式 变量 类型基础数据类型的注解var_1: int 10 没有注解的 var_1 10var_2: float 3.1415926 var_2 3.1415926var_3: bool Truevar_4: str ‘ZEN’var_5: list [1,2,3]var_6: set {1,2,3}var_7: dict {“key”xx}var_8: tuple (1,2,4)class Person:passper Person Person()一般无法直接一眼看出的才注解# 函数和方法的形参类型注解语法def函数名(形参名称:类型,形参名称:类型,....)-返回值类型passdefadd(x:int,y:int)-返回值类型returnxyUnion 类型var_2:list[Union[int,str,list]] [1,AA,[3.4]]多态自动导包Python 共有属性 私有属性 隐藏属性classPerson:def__init__(self,name,age):self.namename # 公有属性 self.ageage # 公有属性defgreet(self):# 公有方法returnfHello, Im {self.name}# 完全可访问pPerson(Alice,25)print(p.name)#Aliceprint(p.age)#25print(p.greet())# Hello,Im Alice############################保护属性Protected- 单下划线 _classPerson:def__init__(self,name,age):self.namename # 公有 self._ageage # 保护属性约定私有 self._salary0# 保护属性 self._init_database()# 保护方法def_init_database(self):# 保护方法内部初始化方法print(初始化数据库连接...)defget_salary(self):returnself._salaryclassEmployee(Person):defshow_info(self):# 子类可以访问保护属性print(fAge: {self._age})print(fSalary: {self._salary})# 使用pPerson(Bob,30)print(p.name)# Bob公有可访问print(p._age)#30可以访问但不建议print(p._salary)#0可以访问但不建议 eEmployee(Alice,25)e.show_info()# 子类可以访问####### 私有属性Private- 双下划线 __classBankAccount:def__init__(self,owner,balance):self.ownerowner # 公有 self.__balancebalance # 私有属性 self.__pin1234# 私有属性self.__transaction_count0# 私有属性def__validate_pin(self,pin):# 私有方法returnpinself.__pindefwithdraw(self,amount,pin):ifself.__validate_pin(pin):ifamountself.__balance:self.__balance-amount self.__transaction_count1returnTruereturnFalsedefget_balance(self,pin):ifself.__validate_pin(pin):returnself.__balancereturnNone# 使用accBankAccount(Alice,1000)# 公有属性可访问print(acc.owner)# Alice# 私有属性不能直接访问# print(acc.__balance) # AttributeError: BankAccount object has no attribute __balance# print(acc.__pin) # AttributeError# acc.__validate_pin(1234)# AttributeError# 通过公有方法访问print(acc.withdraw(100,1234))#Trueprint(acc.get_balance(1234))#900# 名称修饰后的访问方式不推荐print(acc._BankAccount__balance)#900可以但不要这样做print(acc._BankAccount__pin)#1234可以但不要这样做python 与 C# 对象的区别》》python的类属性C#中称为 静态属性可以通过类访问、类修改也可以通过实例对象访问、修改。而C# 中是不可以的》》python的类属性属于类不属于实例对象这个跟C# 一样的》》Python可以动态添加属性实例属性和类属性C#中不行# Python通过实例修改类属性的陷阱classTest:static_list[]# 类属性 static_value100# 类属性 obj1Test()# 对象obj1obj2Test()# 对象obj2# 情况1修改可变对象obj1.static_list.append(1)# 修改的是类属性print(Test.static_list)#[1]-类属性被修改了print(obj2.static_list)#[1]-所有实例共享# 情况2重新赋值obj1.static_value200# 创建实例属性不是修改类属性print(Test.static_value)#100-类属性没变print(obj1.static_value)#200-实例自己的属性print(obj2.static_value)#100-还是类属性# Python动态添加属性classDynamic:pass# 可以在运行时添加类属性Dynamic.new_class_attr动态添加objDynamic()# 可以在运行时添加实例属性obj.new_instance_attr也是动态的print(Dynamic.new_class_attr)# 动态添加print(obj.new_instance_attr)# 也是动态的classAnimal:nameDog _sex公__age20周defAct(self):print(f{self.name}--{self._sex}---{self.__age})animalAnimal()animal.Act()print(animal.name)print(animal._sex)# # 查看所有属性包括修饰后的print(dir(Animal))print(animal._Animal__age)print(animal.__age)#######结果Dog--公---20周 Dog 公[Act,_Animal__age,__class__,__delattr__,__dict__,__dir__,__doc__,__eq__,__firstlineno__,__format__,__ge__,__getattribute__,__getstate__,__gt__,__hash__,__init__,__init_subclass__,__le__,__lt__,__module__,__ne__,__new__,__reduce__,__reduce_ex__,__repr__,__setattr__,__sizeof__,__static_attributes__,__str__,__subclasshook__,__weakref__,_sex,name]20周 Traceback(most recentcalllast):print(animal.__age)^^^^^^^^^^^^AttributeError:Animalobjecthas no attribute __age####################################### _XXXX:单下滑线开头声明私有属性或方法外部可以使用子类也可以继承但是在一个py文件中通过from xxx import * 导入时是无法导入#一般是为了避免与python关键字冲突而采用的命名方法# __XXX:双下划线开头隐藏属性、隐藏方法如果定义在类中无法在外部之间访问子类不会继承# 要访问只能通过间接的方式 不正规的方式1 _类名__属性 正规方式 通过实例方法 获取这个属性# 另一个py文件中通过 from xx import * 导入的时候也无法导入# 这种命名一般是python中的魔术方法或属性都是有特殊含义或者功能的自己不要轻易定义静态方法静态方法是 Python 类中一种特殊的方法类型它既不操作实例没有 self 参数也不操作类没有 cls 参数本质上就是定义在类内部的普通函数。# 定义格式class类名:staticmethod def 方法名(形参) 方法体# 调用的方式 两种类名.方法名(实参)类的对象名.方法名(实参)类方法》使用装饰器 classmethod 修饰的方法就是类的方法。对于类方法第一个参数必须是类对象一般用cls代替# 定义格式class类名:xx123 classmethod def 方法名(cls,形参) cls.xx 方法体# 类方法内部可以访问类属性或者调用其他的类方法。# 调用的方式 两种类名.方法名(实参)类的对象名.方法名(实参)类属性是公共的所有方法内部都能访问到静态方法不需要访问类型属性(但可以访问),因为静态方法和类、对象没有关系实例属性是私有的只有实例方法内部能够访问。抽象方法Python 通过内置的 abc 模块Abstract Base Classes来实现抽象类。fromabcimportABC,abstractmethodclassPayment(ABC):# 继承 ABC支付方式的抽象基类 abstractmethoddefpay(self,amount):支付方法子类必须实现 pass abstractmethoddefrefund(self,amount):退款方法子类必须实现 passdefcommon_method(self):普通方法子类可以直接继承也可以重写print(这是一个通用方法所有支付方式共享)classAlipay(Payment):支付宝支付defpay(self,amount):print(f支付宝支付{amount}元)defrefund(self,amount):print(f支付宝退款{amount}元)classWechatPay(Payment):微信支付defpay(self,amount):print(f微信支付{amount}元)defrefund(self,amount):print(f微信退款{amount}元)# p Payment() # ❌ 报错TypeError不能实例化抽象类alipayAlipay()# ✅ 子类实现了所有抽象方法可以实例化 alipay.pay(100)# 支付宝支付100元 alipay.refund(50)# 支付宝退款50元 alipay.common_method()# 这是一个通用方法所有支付方式共享 wechatWechatPay()# ✅ wechat.pay(200)# 微信支付200元》》》抽象方法可以有默认实现Python 的抽象方法也可以有具体代码子类可以调用父类的抽象方法通过 super()fromabcimportABC,abstractmethodclassAnimal(ABC):abstractmethoddefmake_sound(self):抽象方法也可以有默认实现print(动物发出声音...)# 默认实现 abstractmethoddefmove(self):passclassDog(Animal):defmake_sound(self):# 调用父类的抽象方法虽然是抽象的但可以有实现super().make_sound()print(汪汪汪)defmove(self):print(狗在奔跑)# 使用dogDog()dog.make_sound()# 输出# 动物发出声音...# 汪汪汪》》》抽象属性fromabcimportABC,abstractmethodclassEmployee(ABC):property abstractmethoddefsalary(self):抽象属性 pass salary.setter abstractmethoddefsalary(self,value):抽象 setter passclassDeveloper(Employee):def__init__(self):self._salary0propertydefsalary(self):returnself._salary salary.setterdefsalary(self,value):ifvalue0:raiseValueError(工资不能为负)self._salaryvalue# 使用devDeveloper()dev.salary20000print(dev.salary)#20000

更多文章