【面向对象编程】(2) 类属性的定义及使用;__repr__()方法

本文详细介绍了Python中类属性的定义、使用方法及其在实际编程中的应用。包括如何定义类属性,如何通过实例和类本身访问类属性,以及类属性在计算和存储实例信息中的作用。此外,还讨论了__repr__()方法在显示对象信息时的重要性。
摘要由CSDN通过智能技术生成

各位同学好,在上一节中我们学习了类实例化的基本方法https://blog.csdn.net/dgvv4/article/details/122275348?spm=1001.2014.3001.5501

今天在上一节的基础上继续补充,和大家分享一下类属性的定义及使用方法。


1. 定义类属性

在定义的类中,在初始化函数之前定义到变量称为类属性,是这个类特有的。一旦类实例化之后,那么实例对象默认就可以访问这个类属性。

绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个。也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份

这里定义的类属性 pay_rate,不仅可以通过类来访问 Item.pay_rate,也能通过实例来访问 item1.pay_rate。我们可以通过 __dict__ 查看实例或者类的属性,如最后两行代码,可见类属性pay_rate是属于类Item特有的。

#(1)创建类
class Item:  
    
    #(2)创建类属性
    pay_rate = 0.8  # 定义类属性,代表商品折扣8折
    
    #(3)初始化
    # 第一个参数 self代表类实例化对象,属性name需要字符串类型,属性price需要浮点类型,属性quantity默认值为10
    def __init__(self, name:str, price:float, quantity=10):
        
        # 指定输入输入值的范围,如果不符合就报错,报错内容是逗号后面的
        assert price >=0, f'price {price} cannot smaller than 0'
        assert quantity >=0, f'quantity {quantity} cannot smaller than 0'
        
        # 属性分配
        self.name = name
        self.price = price
        self.quantity = quantity
        
    #(3)在类中定义方法,第一个参数默认是self实例化对象
    def calculate_total_price(self):
        
        # 返回单价和数量的乘积
        return self.price * self.quantity

#(4)类实例化
item1 = Item('phone', 100, 5) # Item类的实例化对象item1,传入各属性对应的值
item2 = Item('MacBook', 1000, 3) 

#(5)调用类中的方法
res = item1.calculate_total_price()
print(res)  # 500

#(6)通过类本身访问类属性
print(Item.pay_rate)  # 0.8

#(7)通过实例化对象访问类属性
print(item1.pay_rate) # 0.8
print(item2.pay_rate) # 0.8


# 打印类的所有属性
print(Item.__dict__)  # {'__module__': '__main__', 'pay_rate': 0.8, '__init__': <function Item.__init__ at 0x0000023A6989A940>, 'calculate_total_price': <function Item.calculate_total_price at 0x0000023A6989ACA0>, '__dict__': <attribute '__dict__' of 'Item' objects>, '__weakref__': <attribute '__weakref__' of 'Item' objects>, '__doc__': None}
# 打印实例的所有属性
print(item1.__dict__)  # {'name': 'phone', 'price': 100, 'quantity': 5}

2. 类属性的应用

在类中定义了一个方法,调用类属性用于计算,self.price * Item.pay_rate,其中price调用的是实例属性pay_rate调用的是类属性,类属性是不变的。

如下代码中,实例属性 price 可根据不同的实例展现不同的值,而类属性 pay_rate 是固定的,通过实例访问类属性改变它的值 item2.pay_rate = 0.5,不会影响 Item.pay_rate 的结果

#(1)创建类
class Item:  
    
    #(2)创建类属性
    pay_rate = 0.8  # 定义类属性,代表商品折扣8折
    
    #(3)初始化,self代表类实例化对象,属性name需要字符串类型,属性price需要浮点类型,属性quantity默认值为10
    def __init__(self, name:str, price:float, quantity=10):
        
        # 指定输入输入值的范围,如果不符合就报错,报错内容是逗号后面的
        assert price >=0, f'price {price} cannot smaller than 0'
        assert quantity >=0, f'quantity {quantity} cannot smaller than 0'
        
        # 属性分配
        self.name = name
        self.price = price
        self.quantity = quantity
        
    #(4)在类中定义方法,第一个参数默认是self实例化对象
    def calculate_total_price(self):
        
        # 返回单价和数量的乘积
        return self.price * self.quantity
    
    #(5)调用类属性
    # 在类中定义方法,用于计算商品折扣
    def apply_discount(self):
        
        # 计算新的价格,pay_rate是Item类自身的属性,在类的内部不能用实例属性self.pay_rate来调用它
        self.price = self.price * Item.pay_rate
        
#(6)Item类的实例化对象item1
item1 = Item('phone', 100, 5)
print(item1.price)  # 100

#(7)调用商品打折的方法
item1.apply_discount()
print(item1.price)  # 80.0

#(8)实例化对象item2
item2 = Item('MacBook', 1000, 3)
print(item2.price) # 1000

# 通过实例化属性改变类属性
item2.pay_rate = 0.5   # 没有发生变化

# 调用类方法 
item2.apply_discount()
print(item2.price)  # 800.0

3. 不同的实例分配不同的类属性

就拿这个案例来说,如果并不是所有的商品都打8折,假如phone打8折,而MacBook打5折,计算时,肯定不能每一次都去重新写类属性。

这时候在调用类属性时,需通过实例访问类属性,用于计算。如下面代码中 self.price = self.price * self.pay_rate,这里的price属性和pay_rate属性都是通过实例来访问的,可以通过实例来改变各属性对应的值。item2.pay_rate = 0.5,就可以将 self.pay_rate 改为0.5

如果是通过类来访问的类属性,那么调用该方法时,即使外部给实例属性赋予了新的值,但是这里仍使用的是类属性的值,没有改变。

#(1)创建类
class Item:
    
    #(2)创建类属性
    pay_rate = 0.8  # 创建类属性,代表商品折扣8折
    
    #(3)初始化,self代表类实例化对象,属性name需要字符串类型,属性price需要浮点类型,属性quantity默认值为10
    def __init__(self, name:str, price:float, quantity=10):
        
        # 指定输入输入值的范围,如果不符合就报错,报错内容是逗号后面的
        assert price >=0, f'price {price} cannot smaller than 0'
        assert quantity >=0, f'quantity {quantity} cannot smaller than 0'
        
        # 属性分配
        self.name = name
        self.price = price
        self.quantity = quantity
        
    #(4)在类中定义方法,第一个参数默认是self实例化对象
    def calculate_total_price(self):
        
        # 返回单价和数量的乘积
        return self.price * self.quantity
    
    #(5)调用类属性
    # 在类中定义方法,用于计算商品折扣
    def apply_discount(self):
        
        # 计算新的价格,类属性pay_rate通过实例属性来访问,可以在外部通过实例来访问这个属性,并改变这个属性的值
        self.price = self.price * self.pay_rate

#(6)类实例化对象
item1 = Item('phone', 100, 5)

#(7)调用类中的商品打折方法(该方法调用类属性)
item1.apply_discount()  # 默认8折
print(item1.price)  # 80.0

# 类实例化对象
item2 = Item('MacBook', 1000, 3)
# 通过实例对象访问类属性,并改变该实例所对应的类属性的值
item2.pay_rate = 0.5
# 调用打折方法,已经改变了属性的值
item2.apply_discount()
print(item2.price)  # 500.0

4. 访问多个实例的属性

现在有很多实例化对象,如何去批量访问这些实例的属性呢。定义一个列表形式的类属性 all_instance,在每一次初始化之后,将定义好了的实例化对象追加到列表中Item.all_instance.append(self) ,这里是通过类来访问类属性,这样外部就改变不了类属性 all_instance 中的值。最后通过一个for循环遍历类属性中的所有实例,打印实例的属性结果。

#(1)创建类
class Item:
    
    #(2)创建类属性
    pay_rate = 0.8  # 创建类属性
    
    all_instance = []  # 存放所有已经定义的实例
    
    #(3)初始化,指定需要传入的实例属性的值是什么类型的
    def __init__(self, name:str, price:float, quantity=10):
        
        # 指定输入输入值的范围,如果不符合就报错,报错内容是逗号后面的
        assert price >=0, f'price {price} cannot smaller than 0'
        assert quantity >=0, f'quantity {quantity} cannot smaller than 0'
                
        # 分配属性
        self.name = name
        self.price = price
        self.quantity = quantity
        
        # 每次初始化后都会将创建好了的实例存追加到列表中
        # 这里通过类访问的类属性,在外部就改变不了all_instance的值
        Item.all_instance.append(self)  # 将实例self追加到列表中
                
    #(4)定义计算总价的方法
    def calculate_total_price(self):
        
        # 返回单价乘数量
        return self.price * self.quantity
    
    #(5)定义打折方法,调用类属性
    def price_discount(self):
        
        # 通过实例访问类属性pay_rate,可在外部通过实例改变类属性的默认值
        self.price = self.price * self.pay_rate

#(6)实例化了很多对象,在完成类初始化之后,都将这些实例存放在all_instance属性中
item1 = Item('phone', 100, 5)
item2 = Item('MacBook', 200, 6)
item3 = Item('ipad', 300, 7)
item4 = Item('Mouse', 400, 8)
item5 = Item('keyboard', 500, 9)

#(7)访问所有实例化对象
for instance in Item.all_instance:
    # 打印所有实例的属性
    print('name:', instance.price, 'price:', instance.price, 'quantity:', instance.quantity)

#(8)直接输出实例化对象
print(Item.all_instance) 
# [<__main__.Item object at 0x0000023A698B7D00>, <__main__.Item object at 0x0000023A698B7250>, <__main__.Item object at 0x0000023A698B7610>, <__main__.Item object at 0x0000023A698B7A60>, <__main__.Item object at 0x0000023A698B7B50>]

5. __repr__() 显示属性

如上面代码的第(8)步,直接输出实例化对象 print(Item.all_instance),本意往往是想了解该对象的基本信息,但默认情况下,我们得到的信息只会是“类名+object at+内存地址”

当我们输出某个实例化对象时,其调用的就是该对象的 __repr__() 方法,输出的是该方法的返回值 print(Item.all_instance)  等同于执行 print(Item.all_instance.__repr__()),程序的输出结果是一样的。

因此,在类中定义 __repr__() 的输出格式 return f"Item('{self.name}', {self.price}, {self.quantity})",这样的话,在外部输出实例化对象时,就可以按照这个格式打印结果了。

#(1)创建类
class Item:
    
    #(2)创建类属性
    pay_rate = 0.8  # 创建类属性
    
    all_instance = []  # 存放所有已经定义的实例
    
    #(3)初始化,指定需要传入的实例属性的值是什么类型的
    def __init__(self, name:str, price:float, quantity=10):
        
        # 指定输入输入值的范围,如果不符合就报错,报错内容是逗号后面的
        assert price >=0, f'price {price} cannot smaller than 0'
        assert quantity >=0, f'quantity {quantity} cannot smaller than 0'
                
        # 分配属性
        self.name = name
        self.price = price
        self.quantity = quantity
        
        # 每次初始化后都会将创建好了的实例存追加到列表中
        # 这里通过类访问的类属性,在外部就改变不了all_instance的值
        Item.all_instance.append(self)  # 将实例self追加到列表中
                
    #(4)定义计算总价的方法
    def calculate_total_price(self):
        
        # 返回单价乘数量
        return self.price * self.quantity
    
    #(5)定义打折方法,调用类属性
    def price_discount(self):
        
        # 通过实例访问类属性pay_rate,可在外部通过实例改变类属性的默认值
        self.price = self.price * self.pay_rate
        
    #(6)显示属性,接收实例
    def __repr__(self):
        
        return f"Item('{self.name}', {self.price}, {self.quantity})"

#(7)实例化多个对象
item1 = Item('phone', 100, 5)
item2 = Item('MacBook', 200, 6)
item3 = Item('ipad', 300, 7)
item4 = Item('Mouse', 400, 8)
item5 = Item('keyboard', 500, 9)

#(8)输出实例化对象,调用的就是该对象的 __repr__() 方法,输出的是该方法的返回值
print(Item.all_instance)
# [Item('phone', 100, 5), Item('MacBook', 200, 6), Item('ipad', 300, 7), Item('Mouse', 400, 8), Item('keyboard', 500, 9)]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立Sir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值