zoukankan      html  css  js  c++  java
  • 【0903 | Day 29】反射和内置方法

    绑定方法和非绑定方法

    总结:

    • @classmethod 是个装饰器,放在类中函数的上面,该函数就变成了类的绑定方法

    • 类的绑定方法由类来调用,自动把类传过去(对象也可以调,一般不用)

    • 类的绑定方法一般用在不需要通过对象,只需要通过类就能完成某些事的时候,该方法定义为类的绑定方法


    一、绑定方法

    绑定方法:绑定给谁就由谁调用,并且将自身传入

    • 类的绑定方法:类中使用 @classmethod 修饰的方法就是绑定到类的方法。这类方法专门为类定制

      class Operate_database():
          host = '192.168.0.5'
          port = '3306'
          user = 'abc'
          password = '123456'
      
          @classmethod
          def connect(cls):  # 约定俗成第一个参数名为cls,也可以定义为其他参数名
              print(cls)
              print(cls.host + ':' + cls.port + ' ' + cls.user + '/' + cls.password)
      
      
      ==>>> Operate_database.connect()
      
      #<class '__main__.Operate_database'>
      #192.168.0.5:3306 abc/123456
      
      Operate_database().connect()
      
    • 对象的绑定方法:在类中没有被任何装饰器修饰的方法就是 绑定到对象的方法,这类方法专门为对象定制。

      class Person:
          country = "China"
      
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def speak(self):
              print(self.name + ', ' + str(self.age))
      
      
      ==>>> p = Person('Kitty', 18)
            print(p.__dict__)
      
      #{'name': 'Kitty', 'age': 18}
      
      ==>>> print(Person.__dict__['speak'])
      
      #<function Person.speak at 0x10f0dd268>
      
      

      注意:speak即为绑定到对象的方法,这个方法不在对象的名称空间中,而是在类的名称空间中。

    二、非绑定方法

    非绑定方法:在类内部使用 @staticmethod 修饰的方法即为非绑定方法,这类方法和普通定义的函数没有区别,不与类或对象绑定,谁都可以调用,且没有自动传值的效果。

    import hashlib
    
    
    class Operate_database():
        def __init__(self, host, port, user, password):
            self.host = host
            self.port = port
            self.user = user
            self.password = password
    
        @staticmethod
        def get_passwrod(salt, password):
            m = hashlib.md5(salt.encode('utf-8'))  # 加盐处理
            m.update(password.encode('utf-8'))
            return m.hexdigest()
    
    
    ==>>> hash_password = Operate_database.get_passwrod('lala', '123456')  # 通过类来调用
    	  print(hash_password)
    
    #f7a1cc409ed6f51058c2b4a94a7e1956
    
    
    ==>>> p = Operate_database('192.168.0.5', '3306', 'abc', '123456')
    	  hash_password = p.get_passwrod(p.user, p.password)  # 也可以通过对象调用
    	  print(hash_password)
    
    #0659c7992e268962384eb17fafe88364
    
    

    注意:简而言之,非绑定方法就是将普通方法放到了类的内部。

    断点调试

    总结:

    • 一等公民:能够将一个东西赋值给一个变量,这个东西就叫一等公民

    • 红色圆圈表示断点标记,程序运行时会在该处暂停

    • 断点应该加在报错的地方之前

    • 绿色箭头表示快速跳到下一个断点执行


    issubclass和isinstance

    总结:

    • issubclass:判断第一个类是不是第二个类的子类,返回true或者false
    • isinstance:判断第一个参数是不是第二个参数的对象,返回true或者false

    issubclass 举个栗子:

    class Foo:
        pass
    class Bar(Foo):
        pass
    class Tt(Bar):
        pass
    
    print(Bar.__bases__) ==>Foo
    print(issubclass(Bar,Foo))  ==>判断Bar是不是Foo的子类, True
    print(issubclass(Tt,object))    ==>新式类默认继承object,所以为True
    

    isinstance 举个栗子:

    class Foo:
        pass
    class Tt():
        pass
    
    f=Foo()  ==>实例化对象
    print(isinstance(f,Foo)) ==>True
    print(isinstance(f,Tt))	 ==>False
    

    反射

    总结:

    • 反射:通过字符串来获取,设置,删除对象中的属性或方法
    • hasattr():判断一个属性是否在对象中,返回True或者False
    • getattr():通过字符串获取属性或方法,如果获取到了,就会返回相应的属性或方法
    • setattr():通过字符串来设置属性或方法
    • delattr():通过字符串来删除属性或方法
    • 拓展:sorted( ).sorted前者为内置函数,后者为绑定方法

    举个栗子:

    class Foo:
        def run(self):
            print('run')
        def speak(self):
            print('speak')
    
    p=Foo()
    print(Foo.__dict__)
    cmd=input('请输入命令:')
    
    #方案一:
    print(Foo.__dict__[cmd])
    Foo.__dict__[cmd](Foo)
    
    #判断一下对象中有没有没有我输入的属性,如果有,打印
    if hasattr(p,cmd):
        run=getattr(p,cmd)
        run()
    else:
        print('该命令不存在')
    

    1. 通过用户输入key和value往对象中赋值

    key=input('请输入key:')
    value=input('输入value:')
    
    setattr(p,key,value)
    print(p.age)
    

    2. 动态的往对象中放方法

    def test(a):
        print(a)
    
    print(p.__dict__)
    setattr(p,'test',test)
    
    print(p.__dict__)
    p.test(0)
    

    3. 动态的删除属性

    #原始的删除方法
    p.name='lqz'
    del p.name
    
    
    #动态删除p中属性为变量a的属性
    p.name='lqz'
    p.age=18
    p.sex='male'
    
    a=input('请输入要删除的属性:')
    delattr(p,a)
    
    
    #直接p.a是不对的
    del p.a
    
    

    最后再举个栗子:

    例子
    class BlackMedium:
        feature='Ugly'
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
    
        def sell_house(self):
            print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
        def rent_house(self):
            print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
    
            
    b1=BlackMedium('万成置地','回龙观天露园')
    
    print(b1.__dict__)
    print(hasattr(b1,'sell_house'))
    
    a='sell_house'
    getattr(b1,'sell_house')
    getattr(b1,a)()
    sell_house=getattr(b1,a)
    name=getattr(b1,'name')
    print(name)
    print(sell_house)
    

    内置方法

    总结:

    • 点拦截方法对象.即触发
    • __setattr__:赋值或修改都将触发
    • __getattr__:一旦在对象中取不到,则会触发
    • __delattr__对象.删除值会触发
    • __str__:print打印时自动触发该函数执行,打印出内存地址,如果重写则会打印出自定义内容
    • __repr__ :__str__类似,在交互式命令下直接写变量名,会执行__repr__
    • item__setitem____getitem__,对象通过[ ] 中括号取值,赋值,删除值的时候,会调用
    • __call__:对象加括号会调用它
    • __enter____exit__:with上下文管理器(本质)

    class Foo:
        x = 1
    
        def __init__(self, y):
            self.y = y
    
        def __getattr__(self, item):
            print('----> from getattr:你找的属性不存在')
    
        def __setattr__(self, key, value):
            print('----> from setattr')
            # self.key = value  # 这就无限递归了,你好好想想
            # self.__dict__[key] = value  # 应该使用它
    
        def __delattr__(self, item):
            print('----> from delattr')
            # del self.item  # 无限递归了
            self.__dict__.pop(item)
    
    

    一、__setattr__

    • 添加/修改属性会触发它的执行

    • 注意:利用该内置方法可以自定义值,而不是不能通过__init__放值

    f1 = Foo(10) #触发self.y,进入__setattr__
    print(f1.__dict__) 
    
    # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
    
    f1.z = 3  #赋值, 进入__setattr__
    print(f1.__dict__)
    

    ----> from setattr
    {}
    ----> from setattr
    {}

    二、__delattr__

    • 删除属性的时候会触发
    f1 = Foo(10)  #----> from setattr
    
    f1.__dict__['a'] = 3  # 我们可以直接修改属性字典,来完成添加/修改属性的操作del f1.aprint(f1.__dict__)python
    print(f1.__dict__)
    del f1.a  #----> from delattr
    print(f1.__dict__)
    

    ----> from setattr
    {'a': 3}
    ----> from delattr
    {}

    三、__getattr__

    • 只有在使用点调用属性,且属性不存在的时候,才会触发
    • 取不到值而调用该方法时,也可以自定义值返回
    f1 = Foo(10)
    f1.bb
    

    ----> from setattr
    ----> from getattr:你找的属性不存在

    写一个类继承字典,让它可以 . 取值,可以中括号取值:

    class Mydict(dict):
        def __init__(self, **kwargs):
            #self.xxx = xxx 原先使用self.某属性,对象加点会调用__setattr__,所以尽量不用
            super().__init__(**kwargs)
    
        def __getattr__(self, item):
            return self[item]
    
        def __setattr__(self, key, value):
            #第一种写法
            self[key] = value 
            
             #第二种写法
            self.__dict__[key] = value
            
            #第三种写法,默认父类为object,此时为重写__setattr__直接赋值
            super().__setattr__(key, value) 
            
    
    di = Mydic(name = 'lqz', age = 18)
    di.name = 'lqz' #不进入__init__,会调用__setattr__,里面有__dict__,name放入key,lqz放入value
    
    
    print(di['name'])
    print(di.name)
    

    ---> lqz
    ---> lqz

    di.sex = 'male'
    di['sex'] = 'male'
    print(di.sex)
    di.sex = 19
    print(di.sex)
    

    ---> male
    ---> 19

    四、__item__系列

    • 对象通过[ ] 中括号取值,赋值,删除值的时候,会调用
    class Foo:
        def __init__(self, name):
            self.name = name
    
        def __getitem__(self, item):
            print('getitem执行', self.__dict__[item])
    
        def __setitem__(self, key, value):
            print('setitem执行')
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            print('del obj[key]时,delitem执行')
            self.__dict__.pop(key)
    
    
    
    1. __setitem__
    • 中括号赋值时触发
    f=Foo('lqz')
    f['age'] = 18
    

    ---> setitem执行

    1. __getitem__
    • 中括号取值时触发
    f=Foo('lqz')
    f['age'] = 18
    f['age']
    

    ---> setitem执行
    ---> getitem执行 18

    f['name'] = 'nick'
    

    ---> setitem执行

    五、__call__

    • 对象加括号会调用它
    class Foo:
        def __call__(self):
            print('xxxx')
    
    f=Foo()()
    

    ---> xxxx

    六、__enter____exit__

    • with上下文管理器(本质)
    class Mydict():
        def __getattr__(self, item):
            print('xxx')
            return '该属性不存在'
    
    m=Mydict()
    print(m.name)
    

    ---> xxx

    ---> 该属性不存在

  • 相关阅读:
    最简单的jQuery插件
    SQL执行时间
    Resharper 8.2 注册码
    Module模式
    RestSharp使用
    使用MVC过滤器保存操作日志
    Ajax Post 类实例
    IBatis分页显示
    IBatis插入类的实例
    Topcoder SRM629 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/fxyadela/p/11453927.html
Copyright © 2011-2022 走看看