python 入门 day26

目录

一、isinstance和issubclass

判断某个对象是不是某个类的实例

isinstance()
判断一个类是不是另一个类的子类(所有类都是object的子类或子子类)

issubclass()

#判断某个对象是不是某个类的实例
# isinstance()

#判断一个类是不是 另一个类的子类(所有类都是object的子类或子子类)
#issubclass


class Person:
    pass


class Student(Person):
    pass


stu = Student()

# 判断两个对象是不是同一类型
print(type(1) == type(1))

#判断stu对象是不是Student类的实例
print(isinstance(stu,Student))

#判断一个类是不是 另一个类的子类(所有类都是object的子类或子子类)
print(issubclass(Student,Person))

二、反射

1.反射的定义

反射即反省,对象要具备一种修正错误的能力

2.反射的方法

hasattr 是否存在某个属性

getattr 获取某个属性的值

setattr 设置某个属性的值

扫描二维码关注公众号,回复: 4571405 查看本文章

delattr 删除某个属性

使用场景:访问的属性不明确

如果在编写代码期间,就能明确知道我要访问的属性,没有必要使用反射

如果在编写代码期间,无法明确知道我要访问的属性,这时就应该使用反射

3.如何使用

通过字符串来操作属性

hasattr(obj, "name")    # stu.name 查看这个属性是否存在
getattr(obj, "name", "没有name属性")    # stu.name 获取这个属性,不存在则:输出没有name属性
setattr(stu, "school", "beijing")   #stu.school = beijing   增加一个school属性
delattr(stu, "school")  #del stu.school 删除学校属性
class Student:
    def __init__(self,name,sex,age):
        self.name = name
        self.age = age
        self.sex = sex

    def study(self):
        print("学生正在学习...")


stu = Student("aigen", "woman", 38)


#当你获取一个对象,但是并不清楚该对象的内部细节时,就需要反射了
def test(obj):
    if hasattr(obj, "name"):        # stu.name 查看这个属性是否存在
        print(getattr(obj, "name", "没有name属性")) # stu.name 获取这个属性,不存在则:输出没有name属性


test(stu)

setattr(stu, "school", "beijing")   #stu.school = beijing   增加一个school属性

delattr(stu, "school")  #del stu.school 删除学校属性

print(getattr(stu, "school", "没有学校属性"))

delattr(stu, "age")

print(stu.age)

反射练习:

# 使用场景:编写代码期间无法明确要访问的属性
class Student:
    def study(self):
        print("学习中...")


stu = Student()

res = getattr(stu, "study", None)

print(res)


def eat(self):
    print("正在吃饭...")

#可以通过反射的方式为对象增加一个方法 但是这样的增加方法就是一个普通函数不会自动传值


setattr(stu, "eat", eat)
print(getattr(stu, "eat", None))

#编写一个CMD工具,这个工具可以支持两个命令 dir,tasklist


class CMD:

    def dir(self):
        print("列出当前文件目录...")

    def tasklist(self):
        print("查看任务列表...")


cmd = CMD()

res = input("请输入指令:").strip()

if hasattr(cmd, res):
    func = getattr(cmd, res)
    print(func)
    func()
else:
    print("输入的指令不正确...")

三、__ str __ 方法

将对象转换成字符串

1.内置函数

函数前后都带有双下划线,会在某些时机自动执行,一般情况不应该直接调用它们。

2.使用

将需要自定义打印的内容通过__ str __方法实现,返回一个字符串

class Test:

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

    def __str__(self):
        print("str run...")
        return self.name


t = Test("安米")

print(int(1).__str__())

print(str(t))   #在将一个对象转换字符串时,本质就是在调用这个

四、__ del __ 方法

析构函数:分析构造,并拆除这个对象

1.执行方式

  • 当对象被从内存中删除时会自动执行
  • 程序员手动删除了这个对象,也会自动执行

2.什么时候使用

当程序运行结束时,需要做一些清理操作,就使用__ del __

import time


class Student:

    def __del__(self):
        print("对象被删除了")


stu = Student()

del stu


time.sleep(1)


class TextFile:

    def __init__(self, filepath, mode="rt", encoding="utf-8"):
        self.file = open(filepath, mode=mode, encoding=encoding)

    def read(self):
        return self.file.read()

    def write(self, text):
        return self.write(text)

    #该方法其实就是一个通知性质,仅仅是告诉程序员,对象即将被删除
    def __del__(self):
        self.file.close()   #关闭系统文件


tf = TextFile("反射.py")

print(tf.read())

# tf.file.close()   手动关闭多余了,在程序运行完一次以后就会删除对象进行关闭

tf.read()

五、exec方法

execute:执行

1.作用

解析执行python代码,并且将得到的名称,存储到制定的名称空间。(解释器内部也是调用它来执行代码)

2.如何使用

参数一:需要一个字符串对象,表示需要被执行的python语句

参数二:是一个字典,表示全局名称空间

参数三:也是一个字典,表示局部名称空间

globalsdic = {}
localsdic = {}

exec("""
aaaaaaaaaa = 1
bbbbbbbbbb = 2
def func1():
    print("我是func1")
""", globalsdic, localsdic)     #globalsdic 也可以用 {}

#如果同时制定了 全局和局部 则会将字符串中包含的名称 解析后存储到局部中
print(globalsdic)
print(localsdic)
localsdic["func1"]()

六、元类

用于产生类的类,type就是元类

所有的自定义类都是通过type实例化得来

一切皆对象

1.创建模块的过程:

  • 创建一个空的名称空间
  • 执行内部的代码
  • 将得到的名字放到名称空间中

2.类的创建过程相似于模块的创建

类是由type实例化产生的

使用type来产生一个类

一个类是由 类名字 类的父类元祖 类的名称空间 三个部分组成

class Student(object):
    school = "北京大学!"

    def study(self):
        print("学习中...")


print(type(Student))    #<class 'type'> Student 的类型为type
                        #类是type类型的实例(对象)

#type实例化一个类
#myclass 包含的代码
code = """
name = "张三"
age = 18
def hello(self):
    print("hello %s" % self.name)
"""

#类的名字
class_name = "MyClass"
#类的父类们
base_classes = (object,)    #必须是个元组
#类的名称空间
namespace = {}

exec(code, {}, namespace)

res = type(class_name, base_classes, namespace)

print(Student)
print(res.name)
print(res.age)
print(res.hello)


class Test(object):     #Test = type("Test", (object,), {})
    pass

七、__ call __ 方法控制对象的实例化过程

1.定义

调用:在对象被调用时 执行

2.自定义元类的目的

  • 可以通过__ call __来控制对象的创建过程
  • 可用控制类的创建过程

3.对象实例化模板

  • 创建空对象
  • 调用初始化方法
  • 得到一个完整的对象
class MyMeta(type):
    def __call__(self, *args, **kwargs):
        obj = object.__new__(self)
        self.__init__(obj, *args, **kwargs)
        return obj
"""

    __call__

    调用的意思
    在在对象被调用时 执行

    函数 类


    自定义元类 的目的
    1.可以通过__call__ 来控制对象的创建过程
    2.可用控制类的创建过程


"""

# 自定义一个元类 元类也是一个类   但是需要继承type
class MyMeta(type):

    # self 表示要创建对象的那个类(Person)  *args是调用Person类时传入的参数
    def __call__(self, *args, **kwargs):

        print("MyMte中的 call run'")
        print(self,*args,**kwargs)

        # 下面的三步是固定写法 一个模板 只要你需要控制对象的创建过程 就应该先把模板写出来

        # 1.创建空对象
        obj = object.__new__(self)
        # 2.调用初始化方法
        self.__init__(obj,*args,**kwargs)
        # self.__init__(obj)
        # 3.得到一个完整的对象
        return obj



# 修改Person类的元类为MyMeta
class Person(metaclass=MyMeta):

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

    def __call__(self, *args, **kwargs):
        print("call run...")


#调用Person这个对象时 执行的是 Person的类(type)中__call__ 方法
p = Person("张三疯",80)

print(p)
# 当调用对象时 会执行该对象所属类中的__call__方法
# p()

print(p.name)
print(p.age)


# class People:
#     def __init__(self,name):
#         self.name = name
#     pass
#
#
# p = People()
# p.anme = 1

八、通过元类控制类的创建过程


# 要控制类的创建过程 只要找到类所属的类 中的__init__即可


class MyMeta(type):

    # self 刚建出来的类
    # 第二个 类的名字
    # 第三个 类的父类们 元组
    # 第四个 这个类传进来的名称空间
    def __init__(self,class_name,bases,namespace):
        print("============================")
        #print(self.__dict__)
        # 我要控制 类的名字  必须 是大写开头
        if not class_name.istitle():
            print("类名 必须大写开头...... ")
            # 该代码是主动抛出异常
            raise TypeError("类名 必须大写开头...... ")
        #要空类的创建 必须包含__doc__这个属性
        if not self.__doc__:
            raise TypeError("类中必须有文档注释.....")

        pass

class Student(metaclass=MyMeta):   # Student = MyMeta("Student",(object,),{})
    """
        这是文档注释  可以通过__doc__来获取
        这是一个学生类
    """

    # 在类的__init__中可以控制该类对象的创建过程
    def __init__(self,name):
        print("-----------------------")
        print(self.__dict__)
        self.name = name

print(Student.__doc__)

# 元类使用总结:
"""
元类是用于创建类的类
学习元类是为了 能控制类的创建过程 以及 类实例化对象的过程
一.
控制类的创建过程
    1.创建一个元类 (需要继承type)
    2.覆盖__init__方法  该方法 会将新建的类对象  类名 父类们 名称空间 都传进来 ,
        可以利用这些信息在做处理
    3.对于需要被控制的类 需要指定metaclass 为上面的元类 
    
二.
控制类实例化对象的过程
     1.创建一个元类 (需要继承type)
     2.覆盖__call__方法 会将 正在实例化对象的类  调用类是传入的参数  都传进来
     3.在__call__方法中 必须要先编写模板代码
        3.1创建空对象
        3.2调用类的__init__方法来初始化这个空对象
        3.3返回该对象
     4.加入你需要控制的逻辑 
     
类的三个组成部分
类名 父类们 名称空间

元类 -> 实例化产生 -> 类 -> 实例化产生 -> 对象


"""

九、单例模式

"""
    单例模式
    一种设计模式(套路)

    单个实例
    一个类如果只有一个实例 那么该类称之为单例

    为什么需要单例

"""


class MyMeta(type):

    obj = None
    def __call__(self, *args, **kwargs):
        if not MyMeta.obj:
            obj = object.__new__(self)
            self.__init__(obj,*args,**kwargs)
            MyMeta.obj = obj
        return MyMeta.obj


#打印机类
class  Printer(metaclass=MyMeta):
    """
    这是一个单例类 请不要直接实例化 使用get方法来获取实例
    """

    obj = None
    def __init__(self,name,brand,type):
        self.name = name
        self.brand = brand
        self.type = type

    def printing(self,text):
        print("正在打印 %s"  % text)

    # 通过该方法来获取对象 可以保证只有一个对象
    # 但是这还不够 因为 还是可以通过调用类产生新对象
    # 就应该使用元类 来控制实例化的过程 __call__
    # 在__call__ 中编写代码 保证每次调用call 都返回同一个实例 即可

    @classmethod
    def get_printer(cls):
        if not cls.obj:
            obj = cls("ES005","爱普生","彩色打印机")
            cls.obj = obj
            print("创建了新的对象")

        return cls.obj

# 以下三个对象 的数据完全相同 但是却 占用三分内存空间
# p1 = Printer("ES005","爱普生","彩色打印机")
# p2 = Printer("ES005","爱普生","彩色打印机")
# p3 = Printer("ES005","爱普生","彩色打印机")

# 现在要处理问题就是  如何能够限制该类 只能实例化一个对象

p = Printer.get_printer()
print(p)

p = Printer.get_printer()
print(p)

p = Printer.get_printer()
print(p)

p = Printer.get_printer()
print(p)

p1 = Printer("ES005","爱普生","彩色打印机")
p2 = Printer("ES005","爱普生","彩色打印机")

print(p1)
print(p2)
# print(p1,p2,p3)


# p1.printing("一本小说....")


猜你喜欢

转载自www.cnblogs.com/wujinsheng/p/10147142.html
今日推荐