zoukankan      html  css  js  c++  java
  • Python

    目录

    • isinstance和issubclass
    • 反射
      • setattr
      • delattr
      • getattr
      • hasattr
    • str__和__repr
    • del
    • item系列
        - getitem
        - setitem
        - delitem
    • new
    • call
    • len
    • hash
    • eq

    1 isinstance和issubclass

    • isinstance(obj,cls)检查是否obj是否是类 cls 的对象
    class A:pass
    a = A()
    print(isinstance(a, A))
    
    # 结果呈现
    True
    
    • issubclass(sub, super)检查sub类是否是 super 类的派生类
    class A:pass
    class B(A):pass
    print(issubclass(B, A))
    print(issubclass(A, B))
    
    # 结果呈现
    True
    False
    

    2 反射

    • 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

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

    • 四个可以实现自省的函数,下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

    • hasattr

    def hasattr(*args, **kwargs): # real signature unknown
        """
        Return whether the object has an attribute with the given name.
        
        This is done by calling getattr(obj, name) and catching AttributeError.
        """
        pass
    
    • getattr
    def getattr(object, name, default=None): # known special case of getattr
        """
        getattr(object, name[, default]) -> value
        
        Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
        When a default argument is given, it is returned when the attribute doesn't
        exist; without it, an exception is raised in that case.
        """
        pass
    
    • setattr
    def setattr(x, y, v): # real signature unknown; restored from __doc__
        """
        Sets the named attribute on the given object to the specified value.
        
        setattr(x, 'y', v) is equivalent to ``x.y = v''
        """
        pass
    
    • delattr
    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
        
        delattr(x, 'y') is equivalent to ``del x.y''
        """
        pass
    
    • 四个方法的使用演示
    # 反射:是用字符串类型的名字 去获取 变量
    name = 1
    eval("print(name)")     # 安全隐患
    
    # 反射:没有安全问题
    # 反射对象中的属性和方法
    class A:
        def func(self):
            print("in func")
    
    a = A()
    a.name = "alex"
    # 反射对象的属性
    ret = getattr(a,"name")     # 通过变量名的字符串形式取到的值
    print(ret)
    print(a.__dict__)
    variable_name = input(">>>")
    # print(getattr(a, variable_name))
    # print(a.__dict__[variable_name])
    
    
    class A:
        def func(self):
            print("in func")
    
    a = A()
    a.name = "alex"
    # 反射对象的方法
    a.func()
    ret = getattr(a,"func")
    ret()
    
    
    class A:
        price = 20
        @classmethod
        def func(cls):
            print("in func")
    
    # 反射类的属性
    # A.price
    print(getattr(A,"price"))
    
    # 反射类的方法: classmethod staticmethod
    # A.func()
    if hasattr(A,"func"):
        getattr(A, "func")()
    
    # 模块
    import test_project.my_module_obj
    # 反射模块的属性
    print(getattr(test_project.my_module_obj,"day"))
    
    # 反射模块的方法
    getattr(test_project.my_module_obj,"wahaha")()
    
    # 内置模块
    def qqxing():
        print("qqxing")
    
    year = 2018
    
    import sys
    # print(sys.modules["__main__"].year)
    
    # 反射自己模块中的变量
    print(getattr(sys.modules["__main__"],"year"))
    
    # 反射自己模块中的函数
    getattr(sys.modules["__main__"],"qqxing")()
    
    varible_name = input(">>>")
    # print(getattr(sys.modules["__main__"], varible_name))
    print(getattr(sys.modules[__name__], varible_name))
    
    # 要反射的函数有参数怎么办
    import time
    print(time.strftime("%Y-%m-%d %H:%M:%S"))
    print(getattr(time, "strftime")("%Y-%m-%d %H:%M:%S"))
    
    # 一个模块中的类能不能反射得到
    import test_project.my_module_obj
    print(getattr(test_project.my_module_obj,"C")())
    
    
    
    # setattr 设置修改变量
    class A:
        pass
    a = A()
    setattr(A,"name","alex")
    setattr(a,"name","nezha")
    print(A.name)
    print(a.name)
    
    # delattr()
    delattr(a,"name")
    print(a.name)
    delattr(A,"name")
    print(A.name)
    
    # my_module_obj.py
    day = "Monday"  # 周一
    
    def wahaha():
        print("wahahaha")
    
    class C:
        pass
    

    3 str__和__repr

    • 改变对象的字符串显示__str__,repr
    • 自定制格式化字符串__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 __repr__(self):
            return 'School(%s,%s)' %(self.name,self.addr)
        def __str__(self):
            return '(%s,%s)' %(self.name,self.addr)
    
        def __format__(self, format_spec):
            # if 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('myschool','北京','私立')
    print('from repr: ',repr(s1))
    print('from str: ',str(s1))
    print(s1)
    
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''
    print(format(s1,'nat'))
    print(format(s1,'tna'))
    print(format(s1,'tan'))
    print(format(s1,'asfdasdffd'))
    
    class A:
        def __str__(self):
            return "A's object"
        def func(self):
            return "wahaha"
    
    a = A()
    print(str(a))   # a.__str__  --> object
    print(a)   # 答应一个对象的时候,就是调用a.__str__
    # object 里有一个 __str__, 一旦被调用,就返回调用这个方法的对象的内存地址
    
    lst = [1, 2, 3, 4, 5]   # 实例化一个列表类的对象
    print(lst)
    
    print('%s:%s' % ("A", a))
    # %s str()  直接打印实际上调的都是 __str__
    
    class Teacher:
        def __init__(self, name, salary):
            self.name = name
            self.salary = salary
        def __str__(self):
            return "Teacher's object : %s" % self.name
        def __repr__(self):
            return str(self.__dict__)
        def func(self):
            return "wahaha"
    
    nezha = Teacher("哪吒", 250)
    print(nezha)
    print(repr(nezha))
    print(">>> %r" % nezha)
    
    • %r repr() 实际上调的是 repr
    • repr 是 str 的备胎,但str不能做repr的备胎
    • print(obj) / '%s'%obj / str(obj)的时候,实际上是内部调用了 obj.__str__方法,如果str方法有,那么它返回的必定是一个str数据类型
    • 如果没有__str__方法,会先找本类中的 __repr__方法,再没有再找父类的 str
    • repr(),只会找 repr, 如果没有找父类的 repr

    4 del

    • 析构方法,当对象在内存中被释放时,自动触发执行。
    • 注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
    class A:
        def __del__(self):      # 析构函数:在删除一个对象前进行一些收尾工作
            print("执行我啦")
    a = A()
    del a       # del 先执行了这个方法,又删除了变量 - - 执行我啦
    print(a)    # NameError: name 'a' is not defined
    
    # 结果呈现
    执行我啦
      File "C:/Users/thinkpad/Envs/daily_test/test_project/面向对象.py", line 1435, in <module>
        print(a)    # NameError: name 'a' is not defined
    NameError: name 'a' is not defined
    
    # 引用计数
    class A:
        def __del__(self):      # 析构函数:在删除一个对象前进行一些收尾工作
            print("执行我啦")
    a = A()
    import time
    time.sleep(3)   # 执行了del 方法 - - 执行我啦
    
    # 结果呈现
    执行我啦
    
    class A:
        def __del__(self):      # 析构函数
            self.f.close()      # 在 a.f 在内存中消失前,先关闭打开的文件
    a = A()
    a.f = open()    # 打开文件 ,在操作系统中打开了一个文件,拿到了文件操作符存在了内存中
    del a           # 删除 a 以后,a.f 拿到了的文件操作符也消失在内存中
    

    5 item系列

    • getitem_setitem__delitem_
    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['age1']=19
    del f1.age1
    del f1['age']
    f1['name']='alex'
    print(f1.__dict__)
    

    6 new

    • 一个类 始终 只有 一个 实例
    • 当你第一次实例化这个类的时候,就创建一个实例化的对象
    • 当你之后再来实例化的时候,就用之前创建的对象
    class A:
        def __init__(self):
            self.x = 1
            print('in init function')
        def __new__(cls, *args, **kwargs):
            print('in new function')
            return object.__new__(A, *args, **kwargs)
    
    a = A()
    print(a.x)
    
    class Singleton:
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                cls._instance = object.__new__(cls, *args, **kw)
            return cls._instance
    
    one = Singleton()
    two = Singleton()
    
    two.a = 3
    print(one.a)
    # 3
    # one和two完全相同,可以用id(), ==, is检测
    print(id(one))
    # 29097904
    print(id(two))
    # 29097904
    print(one == two)
    # True
    print(one is two)
    

    7 call

    • 对象后面加括号,触发执行。
    • 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
    class A:
        def __init__(self,name):
            self.name = name
        def __call__(self, *args, **kwargs):
            """
            打印这个对象中的所有属性
            :param args:
            :param kwargs:
            :return:
            """
            print("执行我啦")
    
            for k in self.__dict__:
                print(k,self.__dict__[k])
    
    a = A("alex")
    a()
    # 等同于
    a = A("alex")()
    
    # 结果呈现
    执行我啦
    name alex
    执行我啦
    name alex
    

    8 len

    class Classes:
        def __init__(self, name):
            self.name = name
            self.student = []
        def __len__(self):
            return len(self.student)
    
    py_ss = Classes("python全栈9期")
    py_ss.student.append("二哥")
    py_ss.student.append("泰哥")
    print(len(py_ss))
    
    # 结果呈现
    2
    

    9 hash

    class A:
        def __init__(self,name,sex):
            self.name = name
            self.sex = sex
        def __hash__(self):
            return hash(self.name + self.sex)
    
    a = A("agg", "男")
    b = A("agg", "男")
    print(hash(a))          # 2067652227830744138
    print(hash(b))          # 2067652227830744138
    c = A("agg", "女")
    print(hash(c))          # 2005968340684947333
    

    10 eq

    class A:
        def __init__(self,name):
            self.name = name
    
    obj1 = A("egg")
    obj2 = A("egg")
    print(obj1 == obj2)     # False
    
    # 比较内存地址
    class A:
        def __init__(self,name):
            self.name = name
        def __eq__(self, other):
            if self.name == other.name:
                return True
            else:
                return False
    
    obj1 = A("egg")
    obj2 = A("egg")
    obj3 = A("egge")
    print(obj1 == obj2)     # True
    print(obj1 == obj3)     # False
    

    11 例1 纸牌游戏

    from collections import namedtuple
    
    Card = namedtuple("Card", ["rank", "suit"])     # rank 牌面大小  suit牌面花色
    # c1 = Card(2, "红心")
    # print(c1)     # Card(rank=2, suit='红心')
    # 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
    
        def __str__(self):
            return json.dumps(self._cards,ensure_ascii=False)      # json 序列化
    
    deck = FranchDeck()
    print(deck[0])          # 第一张牌
    from random import choice
    print(choice(deck))     # 随机抽牌
    print(choice(deck))     # 随机抽牌
    
    from random import shuffle
    shuffle(deck)       # 洗牌
    print(deck._cards[:5])     # 获取前5 个
    print(deck[:5])            # 获取前5 个   item方法
    
    import json
    print(deck)     # 查看所有牌面
    

    12 例2 100个对象 名字和性别和年龄不同

    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(10):
        p_lst.append(Person('egon',i,'male'))
    
    print(p_lst)
    print(set(p_lst))
    # set 依赖对象的 hash eq
    
  • 相关阅读:
    30分钟掌握ES6/ES2015核心内容[上和下], 不错的说
    根据HTML5 获取当前位置的经纬度【百度地图】【高德地图】
    vue2 入门 教程 单页应用最佳实战[*****]
    JavaScript如何比较两个数组的内容是否相同【转】
    推荐下:开源ckplayer 网页播放器, 跨平台(html5, mobile),flv, f4v, mp4, rtmp协议. webm, ogg, m3u8 !
    浅谈 Underscore.js 中 _.throttle 和 _.debounce 的差异[转]
    原生JavaScript插件开发[转]
    性能监控之Spotlight
    Jmeter(三十五)聚合报告
    Jmeter(三十四)Jmeter-Question之“Cookie获取”
  • 原文地址:https://www.cnblogs.com/xiaoqshuo/p/9778261.html
Copyright © 2011-2022 走看看