上穷碧落下黄泉,两处茫茫皆不见——python面向对象类型方法和反射

临邛道士鸿都客,能以精诚致魂魄。
为感君王辗转思,遂教方士殷勤觅。
排空驭气奔如电,升天入地求之遍。
上穷碧落下黄泉,两处茫茫皆不见。
忽闻海上有仙山,山在虚无缥缈间。
楼阁玲珑五云起,其中绰约多仙子。
中有一人字太真,雪肤花貌参差是。
金阙西厢叩玉扃,转教小玉报双成。
闻道汉家天子使,九华帐里梦魂惊。
揽衣推枕起徘徊,珠箔银屏迤逦开。
云鬓半偏新睡觉,花冠不整下堂来。


1 类中的方法

1.1 实例方法

  • 实例方法描述的是对象的行为,声明在类型中,只能通过对象调用
  • 可以访问属性数据和对象数据
class Emperor:

    # 实例方法
    def find(self):
        print("两处茫茫皆不见")


li = Emperor()
li.find()  # 两处茫茫皆不见

1.2 类方法

  • 类方法是声明在类型中的方法,使用@classmethod 装饰
  • 类方法的第一个参数是当前类型cls(约定俗成使用cls,可以使用其他名称)
  • 类方法只能访问类型属性,不能访问实例属性
  • 可以通过类型名称对象引用直接调用
class Master:

    content = "为感君王辗转思,遂教方士殷勤觅。"

    @ classmethod
    def call(cls):
        print("临邛道士鸿都客,能以精诚致魂魄。", end="")
        # 获取类属性需要在前面加cls.
        print(cls.content)


# 类型名称调用
Master.call()  # 临邛道士鸿都客,能以精诚致魂魄。为感君王辗转思,遂教方士殷勤觅。
# 对象引用调用
master = Master
master.call()  # 临邛道士鸿都客,能以精诚致魂魄。为感君王辗转思,遂教方士殷勤觅。

1.3 静态方法

  • 类型中的普通函数,使用@staticmethod 装饰器声明
  • 不能访问实例属性,不能访问类型属性
class Master:

    @ staticmethod
    def find():
        print("为感君王辗转思,遂教方士殷勤觅")


Master.find()  # 为感君王辗转思,遂教方士殷勤觅

1.3 访问范围(边界判断)

方法名称实例方法类方法静态方法
实例属性数据
类属性数据
局部变量数据

2 反射操作

  • 反射是在程序运行过程中,动态的从内存中获取执行状态,根据执行状态动态调用执行,完成具体功能的操作
  • 反射不直接操作对象数据,而是通过字符串的对象描述,交给运行中的程序,程序在运行时获取到字符串描述的对象数据,再去执行对象数据的操作,类比eval()函数
  • 反射可用于调试或容错开发(不确定目标对象是否已经完善了对应的函数/方法,但可以直接调用执行并且保证程序不能出错)

反射方法(内建函数):

  • hasattr(obj, name) 查询对象 obj 中是否有属性 name
  • getattr(obj, name) 获得对象 obj 中属性 name
  • setattr(obj, name, value) 设置对象 obj 中属性 name
  • delattr(obj, name) 删除对象 obj 中属性 name
class Emperor:

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

    def search(self, obj):
        # 用反射判断是否存在对应的方法,输出不同结果
        # 查询属性
        if hasattr(obj, "like"):
            # 获取属性
            res = getattr(obj, "like")
            return res()
        else:
            print("排空驭气奔如电,升天入地求之遍。上穷碧落下黄泉,两处茫茫皆不见。")


class Consort:

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

    def like(self):
        print("楼阁玲珑五云起,其中绰约多仙子。中有一人字太真,雪肤花貌参差是。")


class Person:
    pass


# 创建对象
li = Emperor("李隆基")
yang = Consort("杨玉环")
per = Person()

# 根据反射条件返回结果
li.search(per)  # 排空驭气奔如电,升天入地求之遍。上穷碧落下黄泉,两处茫茫皆不见。
li.search(yang)  # 楼阁玲珑五云起,其中绰约多仙子。中有一人字太真,雪肤花貌参差是。

# 修改
setattr(li, "name", "唐玄宗")
print(li.name)  # 唐玄宗

# 新增(不推荐在类型定义外新增属性)
setattr(li, "age", 52)
print(li.age)  # 52

# 删除
delattr(li, "age")
print(li.age)  # 报错  'Emperor' object has no attribute 'age'

3 单例模式

3.1 设计模式

  • 又称软件设计模式
  • 是一套被反复使用、经过分类编目的代码设计经验总结
  • 可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性
  • 成熟设计模式有20多种

3.2 单例模式

  • 单例模式是设计模式中创建型模式的一种
  • 指项目中某些数据,只能出现一次(如某个类只能能有一个实例)
class Emperor:

    _emperor = None

    def __new__(cls, *args, **kwargs):
        if not cls._emperor:
            cls._emperor = object.__new__(cls)  # 不存在则创建
        return cls._emperor

    def __init__(self, name):  # 每次执行创建初始化仍然回执行,但都是同一个对象
        self.name = name


emp1 = Emperor("李隆基")
print(emp1.name)  # 李隆基
emp2 = Emperor("唐玄宗")
print(emp2.name)  # 唐玄宗
emp3 = Emperor("唐明皇")
print(emp3.name)  # 唐明皇

# 虽然有三个引用变量,但是id是一样的,即始终是同一个对象
print(id(emp1), id(emp2), id(emp3))  # 2178250177224 2178250177224 2178250177224
# 打印出来都是最后一次修改的属性
print(emp1.name, emp2.name, emp3.name)  # 唐明皇 唐明皇 唐明皇

如果只需执行一次初始化:

class Emperor:

    _emperor = None

    # 是否已经初始化的标记
    init_note = False

    def __new__(cls, *args, **kwargs):
        if not cls._emperor:
            cls._emperor = object.__new__(cls)  # 不存在则创建
        return cls._emperor

    def __init__(self, name):
        # 判断是否已经初始化,如果已经未初始化则进行初始化
        if Emperor.init_note is False:
            self.name = name
            # 初始化后修改标记
            Emperor.init_note = True
        # 如果已经初始化则不执行初始化并直接返回
        else:
            return


emp1 = Emperor("李隆基")
print(emp1.name)  # 李隆基
emp2 = Emperor("唐玄宗")
print(emp2.name)  # 唐玄宗
emp3 = Emperor("唐明皇")
print(emp3.name)  # 唐明皇

# 只有第一次创建对象时初始化
print(emp1.name, emp2.name, emp3.name)  # 李隆基 李隆基 李隆基
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值