动态添加属性和方法、访问私有属性、运算符重载

动态添加属性和方法、访问私有属性、运算符重载

参考教程:
Python面向对象提升与收发邮件04
Python面向对象提升与收发邮件05
Python面向对象提升与收发邮件06

动态给实例添加属性和方法

  • 体现了动态语言的特点(灵活)
  • 给一个对象添加的属性和方法对其他对象无影响
  • 动态添加属性
    • 例如
class Person(object):  # 创建类
    pass

per = Person()  # 实例化对象

# 动态添加属性
per.name = "Tom"
print(per.name)

结果为:
Tom
  • 动态添加方法
    • 需要导入types模块中的MethodType
from types import MethodType

class Person(object):  # 创建类
    pass

per = Person()  # 实例化对象

# 动态添加方法
def say(self):  # 要添加的方法
    print("my name is", self.name)

per.speak = MethodType(say, per)  # 相当于偏函数
per.speak()  # 执行speak()函数

结果为:
my name is Tom
  • 思考:如果我们想要限制实例动态添加的属性或方法怎么办?比如,只允许给对象添加name, age, height, weight属性和speak方法
    解决:定义类的时候,定义一个特殊的属性__slots__,可以限制动态添加的属性或方法。若动态添加了限制之外的属性或方法会报错
    例如:
from types import MethodType

class Person(object):  # 创建类
    __slots__ = ("name", "speak")  # 只允许动态添加name和speak

per = Person()  # 实例化对象

# 动态添加属性
per.name = "Tom"
print(per.name)

# 动态添加方法
def say(self):  # 要添加的方法
    print("my name is", self.name)

per.speak = MethodType(say, per)  # 相当于偏函数
per.speak()  # 执行speak()函数

结果:
Tom
my name is Tom

私有属性

两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__属性名
属性直接对外暴露,不安全,没有数据的过滤,解决办法是限制它的访问,即是私有属性
访问私有属性是需要自己写get和set方法
例如:

  1. 方法一
    使用get和set方法
class Person(object):
    def __init__(self, age):
        self.__age = age  # 私有属性
        
    def getAge(self):  # 取出__age的值
        return self.__age  # 返回__age的值

    def setAge(self, age):  # 过滤数据,为__age赋值
        if age < 0:  # 过滤数据
            age = 0
        self.__age = age  # 为__age赋值

per = Person(18)  # 实例化对象

per.setAge(28)  # 赋值
print(per.getAge())  # 调用getAge()方法并打印结果

结果:
28
  1. 方法二
    使用@property函数做装饰器
class Person(object):
    def __init__(self, age):
        self.__age = age  # 私有属性

    @property  # property 函数用作装饰器可以很方便的创建只读属性
    # 方法名为受限制的变量去掉双下划线
    def age(self):  # 取出__age的值,相当于调用getAge
        return self.__age  # 返回__age的值

    @age.setter  # 去掉双下划线.setter,property 的setter方法同样可以用作装饰器
    # 方法名为受限制的变量去掉双下划线
    def age(self, age):  # 过滤数据,为__age赋值,相当于调用setAge,不能放在age(self)函数之前,否则会报错
        if age < 0:  # 过滤数据
            age = 0
        self.__age = age  # 为__age赋值

per = Person(18)  # 实例化对象

per.age = 28  # 相当于调用setAge
print(per.age)  # 相当于调用getAge

结果:
28

运算符的重载

可以对类的专有方法进行重载
类的专有方法:
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算,在python3已经停用,但在python2中可用
可参考:operator — 标准运算符替代函数
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__truediv__: 除运算
__mod__: 求余运算
__pow__: 乘方方法

重载运算符:指的是在类中定义并实现一个与运算符对应的处理方法,这样当类对象在进行运算符操作时,系统就会调用类中相应的方法来处理。
常见重载运算符:常见运算符重载方法
参考:
浅析Python运算符重载
也可参考:
什么是运算符重载,Python可重载运算符有哪些?
Python中类的运算符重载

实例一:

class Person(object):
    def __init__(self, num, name):
        self.num = num
        self.name = name

    def __add__(self, other):
        return self.num + other.num

    def __str__(self):
        return "num = %d" % (self.num)
        # return "num = " + str(self.num)

    def __len__(self):
        print("字符串长度为:", end="")
        return len(self.name)

per1 = Person(1, "Tom")
per2 = Person(2, "Jerry")
print(per1 + per2)  # 调用__add__,相当于print(per1.__add__(per2))
print(per1)  # 调用__str__,相当于print(per1.__str__())
print(per2)  # 调用__str__,相当于print(per2.__str__())
print(len(per1))  # 调用__len__,相当于print(per1.__len__())

结果:
3
num = 1
num = 2
字符串长度为:3

实例二:

class Student(object):  # 创建学生类
    def __init__(self, name, achievement):  # 具有两个属性
        self.name = name
        self.achievement = achievement

    def __pow__(self, power, modulo=None):  # 乘方的重载运算符
        print(self.name + "的成绩的" + str(power) + "次方为:", end="")  # 打印结果
        return (self.achievement) ** power  # 返回学生成绩的power次方的计算结果

    def __lt__(self, other):  # “<” 的重载运算符
        return self.achievement < other.achievement  # 返回比较结果

student1 = Student("Tom", 86)  # 实例化对象
student2 = Student("Linda", 60)
student3 = Student("Jack", 86)
student4 = Student("LiHua", 100)

print(pow(student1, 2))  # 计算学生成绩的平方
print(pow(student4, 2))
print(student1 < student2)  # 引用__lt__重载运算符比较两学生成绩
print(student1 < student3)
print(student1 < student4)

结果:
Tom的成绩的2次方为:7396
LiHua的成绩的2次方为:10000
False
False
True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值