❝Python入门第十三课,主要是学习了面向对象编程的基础概念,类是创建对象的蓝图,实例是具体对象,属性存储数据,方法定义行为,共同构成面向对象编程的基础。
类的定义
语法格式:
# 定义一个类(类名通常用大驼峰写法)class 类名:# 当一个函数被定义在类中时,它就被称为“方法”。# __init__方法又叫:初始化方法,它主要用来给当前实例对象添加属性。# __init__方法收到的参数是:当前正在创建的实例对象、其他自定义参数。# 当我们后期编写代码,对类进行实例化的时候,Python就会自动调用__init__方法,去完成对实例的初始化。def__init__(self, 参数1, 参数2, 参数3):# 通过self给当前实例添加属性,语法格式为:self.属性名 = 属性值 self.属性名1 = 参数1 self.属性名2 = 参数2 self.属性名3 = 参数3
语法解析:
- 类名通常采用大驼峰命名法,如:Person、UserInfo。
- __init__方法叫初始化方法,当我们对类进行实例化时,Python会自动调用 __init__方法。
- __init__方法的名字不能更改 ,否则 Python 无法自动调用。
- __init__收到的第一个参数是当前正在创建的实例对象,形参通常用 self。
- __init__方法收到的除 self 以外的参数,通常用来设置实例的属性值,通过“点”语法实现:self.属性名 = 属性值。
示例代码:
classPerson:def__init__(self, name, age, gender): self.name = name self.age = age self.gender = gender
创建实例
语法格式:
实例名 = 类名(参数1, 参数2, ...)
实例代码:
classPerson:def__init__(self, name, age, gender): print('创建了一个实例对象:', name, age, gender) self.name = name self.age = age self.gender = gender# 创建Person的实例对象p1 = Person('张三', 18, '男')p2 = Person('李四', 22, '女')# 运行后控制台打印如下:# 创建了一个实例对象: 张三 18 男# 创建了一个实例对象: 李四 22 女# 直接打印一个实例的话,是看不到实例身上的属性。print(p1) # <__main__.Person object at 0x0000026AE1786900>print(p2) # <__main__.Person object at 0x0000026AE18B4910>
通过实例的“点”语法,可以访问或修改实例的属性。
# 访问实例的属性print(f'我叫{p1.name},{p1.age}岁,性别{p1.gender}') # 我叫张三,18岁,性别男print(f'我叫{p2.name},{p2.age}岁,性别{p2.gender}') # 我叫李四,22岁,性别女# 修改实例的属性p2.age = 20print(f'我叫{p2.name},{p2.age}岁,性别{p2.gender}') # 我叫李四,20岁,性别女
通过 实例.__dict__的方式,可以查看实例身上的所有属性(字典形式)。
print(type(p1.__dict__), p1.__dict__) # <class 'dict'> {'name': '张三', 'age': 18, 'gender': '男'}print(type(p2.__dict__), p2.__dict__) # <class 'dict'> {'name': '李四', 'age': 20, 'gender': '女'}
在创建实例完毕后,也可以通过实例.属性名 = 值的形式,给实例追加属性。
p1.address = '北京海淀银角大厦'print(p1.__dict__ # {'name': '张三', 'age': 18, 'gender': '男', 'address': '北京海淀银角大厦'}
通过type()函数,可以查看某个实例对象,是由哪个类创建出来的。
print(type(p1)) # <class '__main__.Person'>print(type(p2)) # <class '__main__.Person'>
自定义方法(方法)
语法格式:
def 方法名(self, 参数1, 参数2)
语法解析:
- 自定义方法的第一个参数是self,是调用该方法的实例对象。
- 自定义方法是保存在类身上的,类的实例对象上没有自定方法,但所有类的实例对象都可以调用类的自定方法。
示例代码:
classPerson:def__init__(self, name, age, gender): self.name = name self.age = age self.gender = gender# 自定义方法defspeak(self, msg): print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说{msg}')# 创建Person的实例对象p1 = Person('张三', 18, '男')p2 = Person('李四', 22, '女')# 调用自定义方法p1.speak('时光不可追')p2.speak('hahah')
实例属性
定义:
通过实例.属性名 = 值定义在实例身上的属性,称为实例属性。
特点:
- 每个实例都有自己的独立一份的实例属性,各个实例之间是互不影响的。
- 实例属性只能通过
实例.属性名访问和修改,不能通过类名访问或修改。
注意:进行实例.属性名 = 值操作时,只会对实例自身的属性起作用,有则修改,无则添加。
示例代码:
classPerson:def__init__(self, name, age, gender):# print('创建了一个实例对象:', name, age, gender) self.name = name self.age = age self.gender = genderdefspeak(self, msg): print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说:{msg}')# 创建Person的实例对象p1 = Person('张三', 18, '男')# 定义实例属性p1.phone = '18700001231'# 查看所有实例属性print(p1.__dict__)# 访问实例属性print(p1.phone)# 通过类访问实例属性报错,所以不能通过类访问实例属性print(Person.phone) # 运行时报错:AttributeError: type object 'Person' has no attribute 'phone'
类属性
定义:
在类中直接写赋值语句(如:a = 100),就会在类身上添加一个 a 的属性,值为 100。
此时 a 就是类属性,它属于类本身,由类所拥有,并且该类创建出来的所有实例对象,都能去访问 a 属性。
特点:
- 所有实例访问的,都是同一个类属性,所以类属性通常用于存放公共数据。
示例代码:
classPerson:# 定义类属性 max_age = 120 planet = '地球'def__init__(self, name, age, gender):# print('创建了一个实例对象:', name, age, gender) self.name = name self.gender = gender# 使用类属性限制 age 的最大值if (age <= Person.max_age): self.age = ageelse: print(f'年龄超出范围了,已将年龄设置为最大值:{Person.max_age}') self.age = Person.max_agedefspeak(self, msg): print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说:{msg}')# 创建Person的实例对象p1 = Person('张三', 18, '男')p2 = Person('李四', 22, '女')# 分别打印类和实例的属性,查看类属性的归属print(Person.__dict__)print(p1.__dict__)# 通过类访问类属性print(Person.max_age)# 通过实例对象访问类属性print(p1.max_age)print(p2.max_age)# 测试对年龄的限制p3 = Person('王五', 138, '男')print(p3.__dict__)
实例方法
定义:
类中所定义的方法,最终会保存在类身上,并且主要是通过实例调用,所以叫实例方法。
特点:
- 实例方法虽然最终保存在类身上,但它主要是供实例使用的,所以才叫实例方法。
- 因为收到了self 参数,所以其内部可以:访问实例属性,调用实例方法。
示例代码:
classPerson: max_age = 120 planet = '地球'def__init__(self, name, age, gender):# print('创建了一个实例对象:', name, age, gender) self.name = name self.gender = gender# 限制 age 的最大值if (age <= Person.max_age): self.age = ageelse: print(f'年龄超出范围了,已将年龄设置为最大值:{Person.max_age}') self.age = Person.max_age# 实例方法defspeak(self, msg): print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说:{msg}')# 实例方法defrun(self, distance): print(f'{self.name} 今日累计步行 {distance} 米')# 创建Person的实例对象p1 = Person('张三', 18, '男')p2 = Person('李四', 22, '女')# 通过实例调用实例方法p1.speak('这是我坚持徒步锻炼的第99天')p1.run(6000)print('*' * 10, '分割线', '*' * 10)p2.speak('这是我坚持徒步锻炼的第299天')p2.run(10000)# 运行结果如下:# 我叫张三,年龄18,性别是男,我想说:这是我坚持徒步锻炼的第99天# 张三 今日累计步行 6000 米# ********** 分割线 **********# 我叫李四,年龄22,性别是女,我想说:这是我坚持徒步锻炼的第299天# 李四 今日累计步行 10000 米
类方法
定义:
使用@classmethod装饰器修饰的自定义方法,第一个参数是类本身,通常用形参cls接收。
特定:
- 可通过类名或实例名调用,但强烈推荐通过类名调用以体现语义。
- 一般用于实现与类相关的逻辑,如:操作类级别的信息、工厂方法等。
from datetime import datetimeclassPerson: max_age = 120 planet = '地球'def__init__(self, name, age, gender):# print('创建了一个实例对象:', name, age, gender) self.name = name self.gender = gender# 限制 age 的最大值if (age <= Person.max_age): self.age = ageelse: print(f'年龄超出范围了,已将年龄设置为最大值:{Person.max_age}') self.age = Person.max_age# 实例方法defspeak(self, msg): print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说:{msg}')# 实例方法defrun(self, distance): print(f'{self.name} 今日累计步行 {distance} 米')# 类方法 @classmethoddefchange_planet(cls, value): cls.planet = value# 类方法 @classmethoddefcreate(cls, info_str):# 从info_str中获取到有效信息 name, year, gender = info_str.split('-')# 获取当前年份 current_year = datetime.now().year# 计算年龄 age = current_year - int(year)# 创建并返回一个Person类的实例对象return cls(name, age, gender)# 创建Person的实例对象p1 = Person('张三', 18, '男')p2 = Person('李四', 22, '女')# 验证:类方法保存在类身上print(Person.__dict__)# 类方法通过类调用Person.change_planet('火星')print(Person.__dict__) # 运行结果可以看到,类属性planet已被修改print(Person.planet)# 通过该实例对象访问类属性,结果同样类属性已被修改print(p1.planet)print(p2.planet)# 测试通过类方法create创建一个实例对象p3 = Person.create('远方-1985-男')print(p3.__dict__)p3.speak('这是我坚持徒步锻炼的第9999天')p3.run(10000)
静态方法
定义:
使用@staticmethod装饰器修饰的自定义方法,方法没有self或cls参数,只是单纯定义在类中。
特点:
- 可通过类名或实例名调用,但强烈推荐通过类名调用以体现语义。
- 由于没有
self或cls参数,所以静态方法中通常:不能访问类属性,也不能访问实例属性。
# 验证:类方法保存在类身上print(Person.__dict__)# 静态方法需要通过类调用result = Person.is_adult(2003)print(result)result2 = Person.mask_idcard('142019199501270017')print(result2)
总结,本文主要学习面向对象编程的一些基础概念,下一篇文章将学些面向对象编程的进阶知识多重继承、多态等。