OOP-面向对象(三)
阅读原文时间:2023年07月08日阅读:1

魔术方法的使用

# 使用 __new__ 创建单态模式
class Singleton():
    __obj = None
    def __new__(cls, *args, **kwargs):
        if cls.__obj is None:
            cls.__obj = object.__new__(cls)
        return cls.__obj

obj1 = Singleton()
obj2 = Singleton()

print(id(obj1), id(obj2))
# 140484580496528 140484580496528

# __new__() 是一种负责创建类实例的静态方法,该方法会优先 __init__() 初始化方法被调用。
# 如果 __new__ 方法返回其他类的实例化。则不会在本类中执行 __init__ 方法


#__call__ 魔术方法
'''
    触发时机:把对象当作函数调用的时候自动触发
    功能: 模拟函数化操作
    参数: 参数不固定,至少一个self参数
    返回值: 看需求
'''

#__del__ 魔术方法(析构方法)
'''
    触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
    功能:对象使用完毕后资源回收
    参数:一个self接受对象
    返回值:无
'''

### 与类相关的魔术属性

# __dict__ 获取对象或类的内部成员结构
# __doc__  获取对象或类的内部文档
# __name__ 获取类名函数名
# __class__ 获取当前对象所属的类
# __bases__ 获取一个类直接继承的所有父类,返回元组

类中的方法

# (1) 普通方法
# (2) 绑定方法:①绑定带对象 ②绑定到类
# (3) 静态方法:无论是对象还是类调用静态方法,都不用传递任何参数

class adog():

    # 普通无参方法
    def tail():
        print('小狗喜欢摇尾巴')
    # 绑定到对象方法
    def wangwang(self):
        print('小狗看到陌生人就旺旺')
    # 绑定到类方法
    @classmethod
    def tian(cls):
        print('小狗喜欢舔舌头')

    # 静态方法
    @staticmethod
    def jump(something):
        print('小狗喜欢接{}'.format(something))

# 普通无参方法
adog.tail()
obj = adog()
# obj.tail() # TypeError

# 绑定到对象方法
obj.wangwang()

# 绑定到类方法
adog.tian()
obj.tian()

# 静态方法
obj.jump('111')
adog.jump('222')

property

# 用property类装饰器,修饰的方法,变为描述符
# 效果:把类中方法变为属性使用,用来控制描述符的获取,设置,删除

class MyClass():
    def __init__(self, name):
        self.name = name

    @property  # 获取
    def username(self):
        return self.name

    @username.setter  # 设置
    def username(self, val):
        self.name = val

    @username.deleter  # 删除
    def username(self):
        del self.name

# 获取属性的值
obj = MyClass('小红')
print(obj.username)

# 修改属性的值
obj.username = '小明'

# 删除属性的值
del obj.username

#========================
# 方法二
class MyClass():
    def __init__(self, name):
        self.name = name

    # 获取
    def get_username(self):
        return self.name

    # 设置
    def set_username(self, val):
        self.name = val

    # 删除
    def del_username(self):
        del self.name

    username = property(get_username, set_username, del_username)

# 获取属性的值
obj = MyClass('小红')
print(obj.username)

# 修改属性的值
obj.username = '小明'

# 删除属性的值
del obj.username

反射

通过字符串操作类对象 或者 模块中的相关成员的操作

① hasattr() 检测对象/类是否有指定的成员

② getattr() 获取对象/类成员的值

③ setattr() 设置对象/类成员的值

④ delattr() 删除对象/类成员的值

# part1 通过字符串反射 类 / 对象 中的成员
class Myclass():
    def __init__(self, name, sex):
        self.name = name
        # 男 请输入 1 否则输入 0
        self.sex = sex

    def hobby(self):
        print('{}爱好{}'.format(self.name, '女' if self.sex == '男' else '男'))

# ① hasattr() 检测对象、类是否有指定的成员
# 对象
obj = Myclass('张三', '男')
res = hasattr(obj, 'name')  # True
res = hasattr(obj, 'hobby')  # True

# 类
res = hasattr(Myclass, "name") # 由于没有初始化,不会执行__init__ ,所有下面返回 False
res = hasattr(Myclass, "hobby")  # True

# ② getattr() 获取对象 / 类成员的值
res = getattr(obj, 'name1', '没有当前对象的成员')
print(res) # 没有当前对象的成员

res_func = getattr(obj, 'hobby')
res_func() # 张三爱好女

# ③ setattr() 设置/添加 对象 / 类成员的值
setattr(obj, 'name', '李四')
obj.hobby() # 李四爱好女

setattr(obj, 'education', '专科')
print(obj.education)

# ④ delattr() 删除对象 / 类成员的值
delattr(obj, 'education')

# part2 通过字符串反射 模块 中的成员
# sys.modules 返回一个系统字典,字典的键是加载的所有模块
#字典中的__main__这个键对应的是当前文件的模块对象;
def f1():
    print('这是f1函数')

import sys
module = sys.modules['__main__']
res = getattr(module, 'f1')
res()