类属性和实例属性
- 创建一个类,也是一个对象,里面有类属性,和实例属性。
- 创建实例对象,实际上__new__创建对象,通俗说开辟了一个新的内存空间,然后调用__init__方法进行初始化,产生一个name,而self指向该实例的内存空间,每一个实例对象都有一个class指向类对象。
- 类对象是唯一的,而实例对象可以有N个。
- 类属性在内存中只保存一份,实例属性在每个对象中都要保存一份。
实例方法、静态方法和类方法
实例对象修改类属性:
创建一个实例方法,传入的是实例对象。
1.obj1.country ='xxxx’这样无法修改类属性,而是在实例对象中增加了一个country属性
2.通过,obj1__.class__.country = ’xxx‘可以对类属性进行修改。
类对象修改类属性:
创建一个类方法,传入的是类对象。对其类属性进行修改。
静态方法:
创建一个静态方法,该方法既不传入实例对象,也不传入类对象。放在类内,调用self.test()。
对比
相同点:对于所有的方法而言,均属于类,所以在内存中也只保存一份。
不同点:方法调用者不同、调用方法时传入的参数不同。
- 调用三种方法传入对象不一样
实例方法:传入列对象
类方法:传入类对象
静态方法:没有参数传入 - 调用者不一样
类对象只能调用类方法和静态方法
实例对象可以调用实例方法、类方法和静态方法,但是在调用的类方法时,传入的是类对象。
举例
import traceback
class Dog:
dogbook = {"黄色":30, "黑色":20, "白色":0}
def __init__(self, name, color, weight):
self.name = name
self.color = color
self.weight = weight
#此处省略若干行,应该更新dogbook的数量
#实例方法: 定义时,必须把self作为第一个参数,可以访问实例变量,只能通过实例名访问
def bark(self):
print("{},叫了起来".format(self.name))
#类方法:定义时,必须把类作为第一个参数,可以访问类变量,可以通过实例名或类名访问
@classmethod
def dog_num(cls):
num = 0
for v in cls.dogbook.values():
num = num + v
return num
#静态方法:不强制传入self或者cls, 他对类和实例都一无所知。不能访问类变量,也不能访问实例变量;可以通过实例名或类名访问
@staticmethod
def total_weights(dogs):
total = 0
for o in dogs:
total = total + o.weight
return total
# 1. 类对象,调用类方法
print("类对象,调用类方法:共有 {} 条狗".format(Dog.dog_num()))
print('-'*20)
# 2. 实例化对象,调用实例方法
d1 = Dog("大黄", "黄色", 10)
d1.bark()
print('-'*20)
# 3. 实例化对象,调用类方法
print("实例化对象,调用类方法:共有 {} 条狗".format(d1.dog_num()))
print('-'*20)
d2 = Dog("旺财", "黑色", 8)
d2.bark()
print('-'*20)
# 4. 实例对象,调用静态方法
print("实例对象,调用静态方法:狗一共重{}".format(d1.total_weights([d1, d2])))
print('-'*20)
# 5. 类对象,调用静态方法
print("类对象,调用静态方法:狗一共重{}".format(d1.total_weights([d1, d2])))
print('-'*20)
# 6. 类对象调用实例方法
try:
Dog.bark()
except:
info = traceback.format_exc()
print(info)
else:
print('no error')
finally:
print('-'*20)