• day28 面向对象的进阶 反射 和类的内置方法


     一、上节回顾:

      #包

      #hashlib

        #登录验证,密文密码检测

          #密文cunc

          #加盐

          #动态加盐

        #检测文件一致性   MD5

          #MD5.update()

      #configparse:配置文件相关

        #网络变成 ftp

        #[section]

        #ol=yes

      #logging:日志

        #记录一些信息和结果

        #打日志

        #日志和print

        #学生管理系统

          #需要用户选择的时候打印提示信息

          #一个程序和用户发生文字交互的时候,不能使用logging

        #中间结果,错误提示么都可以使用logging

        #管理员在某时刻创建了一个班级————logging

    二、今日内容:  

     (1)内置函数  ***

      (2)反射*****

      (3)类的内置双下方法 ***

      (4)面向对对象的高级代码和一道面试题

          #看书

          #看源码

          #看博客

            #简书

            #csdn

    (一)内置函数

    #property

    #classmethod

    #saticmethod

    #super

    #object

    #isinstance

    1、isinstance

        (对象,类)判断这个对象是不是这个类或者这个类的子类的实例化

    from collections import Iterable
    print(isinstance([],Iterable))  #True
    
    class A:pass
    class B(A):pass
    b=B()
    print(isinstance(b,A))  #True
    print(isinstance(b,object))#True

    2、issubclass

      (子类,类)判断一个类是否是另一个类的子类

    class A:pass
    class B(A):pass
    print(issubclass(B,A))   #True
    print(issubclass(A,B))  #False
    print(issubclass(A,object))  #True
    print(issubclass(B,object))  #True

    3、补充:注释的添加

    函数的注释添加

    4、vars

    # 看全局
    # a=1
    # b=2
    # print(vars())
    # print(dir())
    
    class A:
        c=1
        d=2
        def func(self):
            self.name="alex"
    # 看类
    # print(vars(A))
    a=A()
    a.func()
    # 看对象
    print(vars(a))   #{'name': 'alex'}

    (二)反射(非常重要)

    对象的反射

    类的反射

    模块的反射

    #hasattr()

    #getattr()

    #setattr()

    #delattr()

    python面向对象中的反射:通过字符串的形式操作相关的属性。python中一切事物的对象都可以使用反射

    1、getattr(与eval的区别在于getattr不会存在的信息会报错,比较安全

    class Management:
        role="管理员"
        def __init__(self,name,sex,phone,mail):
            self.name=name
            self.sex=sex
            self.phone=phone
            self.mail=mail
        def creat_class(self):
            print("创造了一个班级信息")
        def creat_teacher(self):
            print("创造了一个老师信息")
        def creat_student(self):
            print("创造了一个学生信息")
    manager=Management("小鱼","",12331234567,"xiaoyu@qq.com")
    func=input("func: ")
    f=getattr(manager,func)
    f()
    getattr 管理信息的应用

    解析:

      (1)方法名的调用

    cs=getattr(manager,"creat_class")  使用字符串数据类型的方法名调用方法
    cs()  #创造了一个班级信息

    (2)属性的取用

    #属性的的调用
    f=getattr(manager,"phone")  #使用字符串数据类型的变量名获取属性值
    print(f)  #12331234567

    2、hasattr

    (1)hasattr和getattr 组合调用

    import logging
    manager=Management("小鱼","",12331234567,"xiaoyu@qq.com")
    if hasattr(manager,"sex1"):
        sex=getattr(manager,"sex1")   #使用字符串数据类型的变量名获取属性值
        print(sex)
    else:
        logging.warning("没有您输入的属性")
    #WARNING:root:没有您输入的属性

    (2)类名的使用

    if hasattr(Management,"role"):
        print(getattr(Management,"role")) #管理员

    3、setattr  delattr(了解)字符串类型

    # Management.Country="China"
    setattr(Management,"Country","China")  #增加
    print(Management.Country)  #China
    # del Management.Country
    delattr(Management,"Country")   #s删除
    # print(Management.Country)

     (1)对象添加属性:

    (2)使用delattr 删除一个类中的方法

    delattr(Management,"creat_class")
    manager.creat_class()

    (3)绑定的方法(不常用)

    def create_course(self):
        print("创建了一个课程")
    setattr(manager,"create_course",create_course)
    manager.create_course(manager)

    总结:python的一切皆对象

     hasattr(类名(或者对象名),“属性名”)  返回True 或False

    属性值=getattr(类名(或者对象名),“属性名”)

    方法的内存地址=getattr(类名(或者对象名),“方法名”)

    方法的内存地址()

    (三)模块的反射

    1、创建一个模块

    2、调用模块中的属性

    import demo
    print(getattr(demo,"a"))
    #1

    3、调用模块中的函数

    import demo
    qq=getattr(demo,"qqxing") #调用函数名
    qq("wahaha")   #给定一个参数
    #qqxing: wahaha

    4、接收模块中函数的返回值

    import demo
    qq=getattr(demo,"qqxing") #调用函数名
    ret=qq("wahaha")   #给定一个参数
    print(ret)    #接收函数的返回值
    #qqxing: wahaha
    # 大螃蟹

    5、反射本模块的代码(核心是找到本模块sys.modules[__name__])

    aaa="bbb"
    import sys
    print(sys.modules[__name__])
    print(getattr(sys.modules[__name__],"aaa"))
    #bbb

     解析:看有道截图

    总结:

     

    (四)类的内置方法

    __str__和__repr__  改变对象的字符串显示

    1、__str__方法

    class A:
        pass
    def __str__(self):
        return "A的对象"
    a=A()
    print(a)
    print(a.__str__())
    #打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值
    print("%s"%a)

    解析:

    2、__repr__方法

    (1)注释__repr__方法

    class A:
        pass
        def __str__(self):
            return "A的对象"
    
        #def __repr__(self):
            #return "repr:A 的对象"
    a=A()
    print(a)
    print(a.__str__())
    print("%s"%a)
    # A的对象
    # A的对象
    # A的对象

    (2)注释__str__方法

    class A:
        pass
        def __str__(self):
            return "A的对象"
    
        # def __repr__(self):
        #     return "repr:A 的对象"
    a=A()
    print(a)
    print(a.__str__())
    print(a.__repr__())
    print("%s"%a)    #s=str
    print("%r"%a)    #r=repr
    print(str(a))
    print(repr(a))
    # A的对象
    # A的对象
    # <__main__.A object at 0x000000000220D630>
    # A的对象
    # <__main__.A object at 0x000000000220D630>
    # A的对象
    # <__main__.A object at 0x000000000220D630>

    解析:

    3、format(不重要)

    格式化输出:

    format_dict={
        "nat":"{obj.name}-{obj.addr}-{obj.type}",
        "tna":"{obj.type}:{obj.name}:{obj.addr}",
        "tan":"{obj.type}/{obj.addr}/{obj.name}"
    }
    class School:
        def __init__(self,name,addr,type):
            self.name=name
            self.addr=addr
            self.type=type
        def __format__(self, format_spec):
            if not format_spec or format_spec not in format_dict:
                format_spec="nat"
            fmt=format_dict[format_spec]
            return  fmt.format(obj=self)
    s1=School("oldboy1","北京","私立")
    print(format(s1,"nat"))
    print(format(s1,"tna"))
    print(format(s1,"tan"))
    print(format(s1,"erasikfdhkasdffd"))
    # oldboy1-北京-私立
    # 私立:oldboy1:北京
    # 私立/北京/oldboy1
    # oldboy1-北京-私立
    学校的例子
    class School:
        def __init__(self,name,addr,type):
            self.name=name
            self.addr=addr
            self.type=type
        def __format__(self, format_spec):  # format_spec="nat"
            fmt="{obj.type}*{obj.addr}*{obj.name}"
            return  fmt.format(obj=self)
    s1=School("oldboy1","北京","私立")
    print(format(s1,"nat"))
    # 私立*北京*oldboy1
    学校的例子:第二种方法

    解析:

    大作业中的格式化输出:

     4、析构方法:

     

    (1)主动删除(运行步骤从上往下)

    class A:
        def __del__(self):
            print("执行我啦")
    a=A()
    del a
    import time
    time.sleep(2)
    a=A()

    (2)析构函数的应用场景,文件先关闭后删除

    class A:
        def __del__(self):
            self.f.close()
            print("执行我啦")
    f=open("file","w")
    a=A()
    a.f=f
    del f
    import time
    time.sleep(2)

     总结:

    5、item系列

     __getitem__\__setitem__\__delitem__

    (1:访问的方式变了

      #对象名.属性

    class Foo:
        def __init__(self,name):
            self.name=name
        def __getitem__(self, item):
            print(self.__dict__[item])
        def __setitem__(self, key, value):
            self.__dict__[key]=value
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
        def __delattr__(self, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
    
    f1=Foo("sb")
    f1["age"]=18   #给f1添加一个属性
    f1["age1"]=19
    del f1.age1   #删除属性
    del f1["age"]   #删除属性
    f1["name"]="alex"
    print(f1.__dict__)
    # del obj.key时,我执行
    # del obj[key]时,我执行
    # {'name': 'alex'}
    View Code

    关于 item :对象访问,如果是对象名[],是因为内部实现了item系列的方法

    6、__new__方法

    面试的时候会用到

    class Singleton:
        def __new__(cls, *args, **kwargs):
            if not hasattr(cls,"_instance"):
                cls._instance=object.__new__(cls)
            return cls._instance
        def __init__(self,name):
            self.name=name
    one=Singleton("alex")
    print(one.name)
    two=one
    two.name="agon"
    View Code

     

    7、__call__

    class Foo:
        def __init__(self):
            pass
        def __call__(self, *args, **kwargs):
            print("__call__")
    
    obj=Foo()  #执行__init__
    obj() #执行__call__
    
    obj=Foo()()  #对象后面加()就调用__call__
    View Code

     8、__len__方法

    class A:
        def __init__(self):
            self.a=1
            self.b=2
        def __len__(self):
            return len(self.__dict__)
    a=A()
    print(len(a)) #2
    View Code

    9、__hash__

    class A:
        def __init__(self):
            self.a=1
            self.b=2
        def __hash__(self):
            return hash(str(self.a)+str(self.b))
    a=A()
    print(hash(a))
    View Code

    10、__eq__

    class A:
        def __init__(self):
            self.a=1
            self.b=2
        def __eq__(self,obj):
            if self.a==obj.a and self.b==obj.b:
                return True
    a=A()
    b=A()
    print(a==b)#True
    View Code

     纸牌游戏

    from collections import namedtuple
    Card=namedtuple("Card",["rank","suit"])
    c1=Card(2,"梅花")
    class FranchDeck:
        ranks=[str(n) for n in range(2,11)]+list("JQKA")
        suits=["红心","方板","梅花","黑桃"]
        def __init__(self):
            self._cards=[Card(rank,suit) for rank in FranchDeck.ranks
                                                        for suit in FranchDeck.suits]
    
        def __len__(self):
            return len(self._cards)
        def __getitem__(self, item):
            return self._cards
    
    deck=FranchDeck()
    print(deck[0])
    from random import choice
    print(choice(deck))
    print(c1.suit)
    纸牌游戏

    可以增加洗牌功能  随机抽牌功能

    class FranchDeck:
        ranks = [str(n) for n in range(2,11)] + list('JQKA')
        suits = ['红心','方板','梅花','黑桃']
    
        def __init__(self):
            self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                            for suit in FranchDeck.suits]
    
        def __len__(self):
            return len(self._cards)
    
        def __getitem__(self, item):
            return self._cards[item]
    
        def __setitem__(self, key, value):
            self._cards[key] = value
    
    deck = FranchDeck()
    print(deck[0])
    from random import choice
    print(choice(deck))
    print(choice(deck))
    
    from random import shuffle
    shuffle(deck)
    print(deck[:5])
    纸牌游戏2

     面试题:

    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __hash__(self):
            return hash(self.name+self.sex)
    
        def __eq__(self, other):
            if self.name == other.name and self.sex == other.sex:return True
    
    
    p_lst = []
    for i in range(84):
        p_lst.append(Person('egon',i,'male'))
    
    print(p_lst)
    print(set(p_lst))
    一道面试题

      

  • 相关阅读:
    20181120-1 每周例行报告
    20181113-2 每周例行报告
    20181030-4 每周例行报告
    20181023-3 每周例行报告
    第六周例行报告
    软件功能说明书final修订
    第十二周——例行报告
    PSP总结报告
    第十一周——例行报告
    PSP Daily软件beta版本——基于NABCD评论,及改进建议
  • 原文地址:https://www.cnblogs.com/number1994/p/8110446.html
Copyright © 2020-2023  润新知