文章目录
三、实例属性和方法
1. 常见的内置方法、属性
- 概述
__方法名__
格式的方法是 Python
提供的 内置方法 /
属性,稍后会给大家介绍一些常用的 内置方法 / 属性
序号 | 方法名 | 类型 | 作用 |
---|---|---|---|
01 | __new__ | 方法 | 创建对象时,会被 自动 调用,无需手动重写 |
02 | __init__ | 方法 | 对象被初始化时,会被 自动 调用,可以被重写 |
03 | __del__ | 方法 | 对象被从内存中销毁前,会被 自动 调用 |
04 | __str__ | 方法 | 返回对象的描述信息,print 函数输出使用 |
- 其他操作
dir(obj)
:可以获得对象的所有属性、方法obj.__dict__
:对象的属性字典pass
:空语句isinstance(对象,类型
: 判断“对象”是不是“指定类型
2. 实例属性——动态绑定属性
- 动态绑定
在实例对象以后,为该对象添加一个属性
注意:
- Python的属性都是动态绑定的
- 动态为对象绑定属性时,给哪个对象绑定了属性,只能哪个对象有该属性,其他对象是没有该属性的
- 如果在方法中引用了该是虚心那么这是没有该属性的对象,调用这个方法时就会报错
class Person(object):
# 第一个方法
def eat(self, food):
print(self.name, '吃', food)
def sleep(self, t):
print(self.name, f'睡了{t}小时')
# 实例对象
tom = Person()
jack = Person()
rose = Person()
# 为对象动态添加属性name
tom.name = 'Tom'
jack.name = 'Jack'
rose.name = 'Rose'
注:
- Python 中的 self 相当于 C++中的 self 指针,JAVA 和 C#中的 this 关键字。
- Python 中, self 必须为构造函数的第一个参数,名字可以任意修改。但一般遵守惯例,都叫做 self。
3. __init__
方法——实例属性
- 概述
这个方法是一个魔法方法,命名规则是前后各有两个下划线,
魔法方法是python当中预设好的、具有特定功能的方法
一般这种方法,不需要手动调用,会自动调用执行
该方法会在创建对象的时候自动调用,并对对象进行初始化
- 作用
构造函数通常用来初始化实例对象的实例属性
class Cat():
# 实现__init__
def __init__(self):
print('init run...', self)
# 绑定属性
self.name = 'Tom'
self.age = '12'
def show(self):
print(self.name, self.age)
tom = Cat()
print(tom.name) # 'Tom'
print(tom.age) # '12'
- 访问属性
类的内部:
self.实例属性名
创建实例对象后,通过实例对象进行访问:
实例对象名.实例属性名
内存:
- (1) 每个对象存储一份,通过对象地址访问。
4. 实例化过程中的参数传递
实例化时传递的参数,其实是传递给了__init__
方法
因此,属性参数应该位于__init__
方法处
class Cat():
def __init__(self, name, age): # 属性参数传递
print('init run...', self)
self.name = name
self.age = age
def show(self):
print(self.name, self.age)
tom = Cat('Tom',12)
print(tom.name) # Tom
print(tom.age) # 12
tom.show() # Tom 12
5. 实例方法
- 概述
实例方法的定义格式如下:
def 方法名(self [, 形参列表]):
函数体
调用格式如下:
对象.方法名([实参列表])
要点:
- 定义实例方法时,第一个参数必须为 self。self 指当前的实例对象。
- 调用实例方法时,不需要也不能给 self 传参。self 由解释器自动传参。
内存:
- 无论创建多少对象,在内存中方法只有一份,并且被所有对象共享。
方法本质上也是属性!只不过是可以通过()执行而已。
- 函数和方法的区别
- 都是用来完成一个功能的语句块,本质一样。
- 方法调用时,通过对象来调用。方法从属于特定实例对象,普通函数没有这个特点。
- 直观上看,方法定义时需要传递 self,函数不需要。
- 实例对象的方法调用本质
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p7ESG0nB-1610896702761)(Media/image-20210105221541872.png)]
即当我们使用:
stu = Student()
stu.say_score()
解释器转换成了
Student.say_score(stu)
我们也可以用这种方法来调用实例方法,但注意必须手动传递实例对象
5. __str__
方法(重点掌握)
- 概述
__str__
方法:格式化显示对象信息
- 格式
def __str__(self):
s = 'name: ' + self.name + ', age: ' + str(self.age) + ', height ' + self.height
return s
注意:
- 必须返回一个返回值
- 且返回值是字符串值
- 说明实例
当一个自定义类,没有实现该方法时,默认打印格式是
- <模块名.类名 object at 地址>
<__main__.Cat object at 0x02176610>
class Cat():
def __init__(self, name, age, height):
# 将三个属性绑定给对象
self.username = name
self.age = age
self.height = height
# 因此每个实例对象都有三个属性:
# username, age, height
tom = Cat('Tom', 1, '50cm')
print(tom.username) # Tom
print(tom.age) # 1
print(tom.height) # 50cm
print(tom) # <__main__.Cat object at 0x000002281F06F588>
# 默认打印实例对象的内容如上
但例如list
对象,则会打印一个列表:
listA = list([1, 2, 3, 4])
print(listA) # [1, 2, 3, 4]
这就是通过修改__str__
后实现的。
因此,通过修改__str__
后,打印实例对象名如下:
class Cat():
def __init__(self, name, age, height):
# 将三个属性绑定给对象
self.name = name
self.age = age
self.height = height
def __str__(self):
s = 'name: ' + self.name + ', age: ' + str(self.age) + ', height ' + self.height
return s
tom = Cat('Tom', 1, '50cm')
print(tom) # name: Tom, age: 1, height 50cm
tom_str = str(tom)
print(tom_str) # name: Tom, age: 1, height 50cm
- 调用该方法的场景
1. 通过 `print()` 函数打印实例对象时,会自动调用该方法,并打印输出return的返回值
2. 通过 `str()` 函数对实例对象进行类型转换时,会自动调用该方法,并传递return的返回值
6. __del__
方法(了解)——垃圾回收机制
__del__方法称为“析构方法”,用于实现对象被销毁时所需的操作。
-
该方法是用来在销毁对象时,回收释放资源使用的方法
-
该方法也是自动调用
-
当在使用 del 对象,或程序结束且有未回收对象时时,会调用该方法
Python 实现自动的垃圾回收,当对象没有被引用时(引用计数为 0),由垃圾回收器 调用__del__
方法。
因此,如果希望在对象被销毁前,再做一些事情,可以考虑使用__del__
方法
class Cat:
def __del__(self):
print('del方法执行...')
tom = Cat()
print('over')
---------------------
控制台输出:
over
del方法执行...
Process finished with exit code 0
7. 类的复合(类中属性是对象)
- 概述
在设计一个类时,类中包含其它类的对象,称为类的复合
人有一条狗
人想听狗叫
'''
人想听狗叫
'''
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self, n):
for i in range(n):
print('Wow...')
class Person():
def __init__(self, name, age):
self.name = name
self.age = age
# 为人添加一个拥有宠物的方法
def add_pet(self, pet):
self.pet = pet
# 人想听狗叫
def listen_dog_bark(self, n):
self.pet.bark(n)
# 测试
tom = Person('Tom', 23)
# 为人添加一条狗
tom.add_pet(Dog('golf', 1))
# 人想听狗叫
tom.listen_dog_bark(3)
存放家具的案例
'''
类的复合
家具案例
'''
class Furniture():
def __init__(self, name, area):
self.name = name
self.area = area
def __str__(self):
return f'{self.name}占用了{self.area}平米'
class House():
def __init__(self, address, area):
self.address = address
self.area = area
self.free_area = self.area * 0.7 # 可用面积
self.furnitures = []
def __str__(self):
s = f'房子地址为{self.address},占地面积为{self.area},剩余面积为{self.free_area}\n家有如下:'
for i in self.furnitures:
s += (str(i) + '\n')
return s
def add_furniture(self, furniture):
if self.free_area - furniture.area >= 0:
self.furnitures.append(furniture)
self.free_area -= furniture.area
else:
print('空间已满,无法添加家具')
home1 = House('淮海路', 120)
home1.add_furniture(Furniture('table', 20))
print(home1)
8. __call__方法
和可调用对象【了解】
定义了__call__方法
的对象,称为“可调用对象”,即该对象可以像函数一样被调用。
- 调用一个函数,实际就是调用了该函数的
__call__方法
class SalaryAccount:
'''工资计算类'''
def __call__(self, salary):
yearSalary = salary*12
daySalary = salary//30
hourSalary = daySalary//8
return dict( monthSalary=salary, yearSalary=yearSalary, daySalary=daySalary
, hourSalary=hourSalary)
s = SalaryAccount()
print(s(5000)) #可以像调用函数一样调用对象的__call__方法
运行结果:
{'monthSalary': 5000, 'yearSalary': 60000, 'daySalary': 166, 'hourSalary': 20}
测试是否为可调用对象
callable(对象)