Python 类和对象别背语法先理解模板和实例的关系面向对象编程听起来很唬人其实核心就两个概念类和对象。类就是模板对象就是根据模板造出来的具体东西。打个比方类是一张员工入职登记表的模板对象就是你拿着这个模板给每个新员工填出来的那张具体表格。Python 里万物皆对象但你自己也能定义类。定义一个类从空壳子开始用class关键字定义一个类类名用帕斯卡命名法首字母大写classPerson:pass# pass 表示啥都不干占个位置# 造一个对象出来pPerson()print(p)# __main__.Person object at 0x...目前这个Person是个空壳子啥用没有。我们需要给它加东西。构造方法__init__对象出生时该干的事__init__是 Python 的构造方法对象被创建的时候自动调用。它的作用就是给对象初始化——设置初始状态、存一些基础数据。classPerson:def__init__(self,name,age):self.namename# 把参数存到对象身上self.ageagedefintroduce(self):print(f我叫{self.name}今年{self.age}岁)# 创建对象的时候传入参数pPerson(Alice,20)p.introduce()# 我叫 Alice今年 20 岁关键点self就是对象本身相当于 Java 里的thisself.name是对象的属性每个对象有自己的独立副本__init__可以有默认参数让某些属性可选classStudent:def__init__(self,name,major计算机科学):self.namename self.majormajor s1Student(Bob)# major 用默认值s2Student(Charlie,数学)# major 自己指定类变量 vs 实例变量共享的和独享的这是刚学 Python 类的时候最容易搞混的地方。实例变量每个对象各有一份互不影响。用self.xxx定义。类变量所有对象共享一份属于类本身。直接在类下面定义不在任何方法里面。classEmployee:# 类变量统计员工总数所有对象共享emp_count0def__init__(self,name):self.namename# 实例变量每个员工的名字各不同Employee.emp_count1e1Employee(张三)e2Employee(李四)print(e1.name)# 张三print(e2.name)# 李四print(Employee.emp_count)# 2所有对象共享什么时候用类变量统计总数、全局配置、默认值等所有对象共用的东西。什么时候用实例变量每个对象各自不同的数据比如名字、年龄、分数。三种方法实例方法、类方法、静态方法1. 实例方法最常用的第一个参数是selfclassPerson:def__init__(self,name):self.namenamedefsay_hello(self):# self 是当前对象print(fHello, Im{self.name})实例方法能访问实例变量和类变量是日常写代码最常用的一种。2. 类方法用classmethod第一个参数是cls类本身classPerson:count0def__init__(self,name):self.namename Person.count1classmethoddefget_count(cls):returncls.count# 返回总人数类方法通常用来操作类变量或者作为工厂方法——用不同方式创建对象。classPerson:def__init__(self,name,age):self.namename self.ageageclassmethoddeffrom_birth_year(cls,name,birth_year):# 用出生年份推算年龄创建对象age2026-birth_yearreturncls(name,age)pPerson.from_birth_year(Alice,2000)# 不用传 age自动算3. 静态方法用staticmethod不需要 self 或 cls静态方法跟类本身没有直接关系只是因为逻辑上属于这个类所以放在里面。它不访问任何实例或类属性。classMathUtils:staticmethoddefis_even(num):returnnum%20# 直接用类名调用不需要创建对象MathUtils.is_even(10)# True继承子类继承父类的东西单继承一个子类只有一个父类classAnimal:def__init__(self,name):self.namenamedefeat(self):print(f{self.name}在吃东西)# Dog 继承 AnimalclassDog(Animal):defbark(self):print(f{self.name}在汪汪叫)dogDog(旺财)dog.eat()# 继承来的dog.bark()# 自己的重写父类方法子类把父类的方法覆盖掉classCat(Animal):defeat(self):# 重写父类的 eatprint(f{self.name}爱吃鱼)catCat(咪咪)cat.eat()# 咪咪 爱吃鱼自己的方法调用父类的方法用super()classBird(Animal):def__init__(self,name,can_fly):super().__init__(name)# 先调父类的 __init__初始化 nameself.can_flycan_fly# 再初始化子类自己的属性defeat(self):super().eat()# 先执行父类的 eatprint(f{self.name}还爱吃虫子)super()的作用是调用父类的同名方法避免硬编码父类名代码更好维护。多继承一个子类有多个父类classFlyable:deffly(self):print(会飞)classSwimmable:defswim(self):print(会游泳)classDuck(Flyable,Swimmable):passduckDuck()duck.fly()# 会飞duck.swim()# 会游泳多继承的问题在于如果多个父类有同名方法Python 按什么顺序找答案是MRO方法解析顺序从左到右。Duck(Flyable, Swimmable)先找 Flyable再找 Swimmable。私有属性名字前面加两个下划线Python 没有真正的私有但用双下划线开头可以隐藏属性classPerson:def__init__(self,name,age):self.namename# 公开的self.__ageage# 私有的defget_age(self):returnself.__age pPerson(Alice,20)print(p.name)# Alice可以访问# print(p.__age) # 报错访问不了print(p.get_age())# 20通过方法访问其实 Python 只是把__age改名叫_Person__age了你非要访问也能p._Person__age但强烈不推荐。私有属性的意义是约定而不是强制——告诉使用这个类的人别碰这个属性。几个特殊方法让对象更像对象方法作用什么时候触发__init__初始化对象创建对象时__str__对象的字符串表示print(obj)或str(obj)__repr__对象的官方字符串表示调试时或在交互式环境直接输入对象名__len__对象的长度len(obj)__str__最常用classBook:def__init__(self,title,author):self.titletitle self.authorauthordef__str__(self):returnf《{self.title}》作者{self.author}bookBook(Python 编程,张三)print(book)# 《Python 编程》作者张三不定义__str__的话print(book)会打印一串看不懂的内存地址。类比java的toString方法
## Python 类和对象:别背语法,先理解“模板“和“实例“的关系
Python 类和对象别背语法先理解模板和实例的关系面向对象编程听起来很唬人其实核心就两个概念类和对象。类就是模板对象就是根据模板造出来的具体东西。打个比方类是一张员工入职登记表的模板对象就是你拿着这个模板给每个新员工填出来的那张具体表格。Python 里万物皆对象但你自己也能定义类。定义一个类从空壳子开始用class关键字定义一个类类名用帕斯卡命名法首字母大写classPerson:pass# pass 表示啥都不干占个位置# 造一个对象出来pPerson()print(p)# __main__.Person object at 0x...目前这个Person是个空壳子啥用没有。我们需要给它加东西。构造方法__init__对象出生时该干的事__init__是 Python 的构造方法对象被创建的时候自动调用。它的作用就是给对象初始化——设置初始状态、存一些基础数据。classPerson:def__init__(self,name,age):self.namename# 把参数存到对象身上self.ageagedefintroduce(self):print(f我叫{self.name}今年{self.age}岁)# 创建对象的时候传入参数pPerson(Alice,20)p.introduce()# 我叫 Alice今年 20 岁关键点self就是对象本身相当于 Java 里的thisself.name是对象的属性每个对象有自己的独立副本__init__可以有默认参数让某些属性可选classStudent:def__init__(self,name,major计算机科学):self.namename self.majormajor s1Student(Bob)# major 用默认值s2Student(Charlie,数学)# major 自己指定类变量 vs 实例变量共享的和独享的这是刚学 Python 类的时候最容易搞混的地方。实例变量每个对象各有一份互不影响。用self.xxx定义。类变量所有对象共享一份属于类本身。直接在类下面定义不在任何方法里面。classEmployee:# 类变量统计员工总数所有对象共享emp_count0def__init__(self,name):self.namename# 实例变量每个员工的名字各不同Employee.emp_count1e1Employee(张三)e2Employee(李四)print(e1.name)# 张三print(e2.name)# 李四print(Employee.emp_count)# 2所有对象共享什么时候用类变量统计总数、全局配置、默认值等所有对象共用的东西。什么时候用实例变量每个对象各自不同的数据比如名字、年龄、分数。三种方法实例方法、类方法、静态方法1. 实例方法最常用的第一个参数是selfclassPerson:def__init__(self,name):self.namenamedefsay_hello(self):# self 是当前对象print(fHello, Im{self.name})实例方法能访问实例变量和类变量是日常写代码最常用的一种。2. 类方法用classmethod第一个参数是cls类本身classPerson:count0def__init__(self,name):self.namename Person.count1classmethoddefget_count(cls):returncls.count# 返回总人数类方法通常用来操作类变量或者作为工厂方法——用不同方式创建对象。classPerson:def__init__(self,name,age):self.namename self.ageageclassmethoddeffrom_birth_year(cls,name,birth_year):# 用出生年份推算年龄创建对象age2026-birth_yearreturncls(name,age)pPerson.from_birth_year(Alice,2000)# 不用传 age自动算3. 静态方法用staticmethod不需要 self 或 cls静态方法跟类本身没有直接关系只是因为逻辑上属于这个类所以放在里面。它不访问任何实例或类属性。classMathUtils:staticmethoddefis_even(num):returnnum%20# 直接用类名调用不需要创建对象MathUtils.is_even(10)# True继承子类继承父类的东西单继承一个子类只有一个父类classAnimal:def__init__(self,name):self.namenamedefeat(self):print(f{self.name}在吃东西)# Dog 继承 AnimalclassDog(Animal):defbark(self):print(f{self.name}在汪汪叫)dogDog(旺财)dog.eat()# 继承来的dog.bark()# 自己的重写父类方法子类把父类的方法覆盖掉classCat(Animal):defeat(self):# 重写父类的 eatprint(f{self.name}爱吃鱼)catCat(咪咪)cat.eat()# 咪咪 爱吃鱼自己的方法调用父类的方法用super()classBird(Animal):def__init__(self,name,can_fly):super().__init__(name)# 先调父类的 __init__初始化 nameself.can_flycan_fly# 再初始化子类自己的属性defeat(self):super().eat()# 先执行父类的 eatprint(f{self.name}还爱吃虫子)super()的作用是调用父类的同名方法避免硬编码父类名代码更好维护。多继承一个子类有多个父类classFlyable:deffly(self):print(会飞)classSwimmable:defswim(self):print(会游泳)classDuck(Flyable,Swimmable):passduckDuck()duck.fly()# 会飞duck.swim()# 会游泳多继承的问题在于如果多个父类有同名方法Python 按什么顺序找答案是MRO方法解析顺序从左到右。Duck(Flyable, Swimmable)先找 Flyable再找 Swimmable。私有属性名字前面加两个下划线Python 没有真正的私有但用双下划线开头可以隐藏属性classPerson:def__init__(self,name,age):self.namename# 公开的self.__ageage# 私有的defget_age(self):returnself.__age pPerson(Alice,20)print(p.name)# Alice可以访问# print(p.__age) # 报错访问不了print(p.get_age())# 20通过方法访问其实 Python 只是把__age改名叫_Person__age了你非要访问也能p._Person__age但强烈不推荐。私有属性的意义是约定而不是强制——告诉使用这个类的人别碰这个属性。几个特殊方法让对象更像对象方法作用什么时候触发__init__初始化对象创建对象时__str__对象的字符串表示print(obj)或str(obj)__repr__对象的官方字符串表示调试时或在交互式环境直接输入对象名__len__对象的长度len(obj)__str__最常用classBook:def__init__(self,title,author):self.titletitle self.authorauthordef__str__(self):returnf《{self.title}》作者{self.author}bookBook(Python 编程,张三)print(book)# 《Python 编程》作者张三不定义__str__的话print(book)会打印一串看不懂的内存地址。类比java的toString方法