zoukankan      html  css  js  c++  java
  • 反射

    一、反射的概念

    1 什么是反射

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

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

    四个可以实现自省的函数

    下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

    二、反射的四种方法

    只要能通过 xx.xx 调用到的东西都可以用反射,如:

    # 类.属性
    # 类.方法
    # 对象.属性
    # 对象.方法
    # 内置模块.属性
    # 自定义模块.属性
    # 模块.类

    ①hasattr

    此方法是用来检查一个对象有没有一个XX,格式为:hansattr(对象,‘XX‘),注意,第二个参数是一个字符串类型的。返回一个布尔值,如下:

     1 class Person:
     2     kind = '人类'
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6         self.changdu = 28
     7     def func(self):
     8         print('func.....')
     9 p = Person('fuyong',18)
    10 
    11 print(hasattr(p,'name'))        #True
    12 print(hasattr(p,'func'))        #True
    13 print(hasattr(Person,'kind'))   #True
    14 print(hasattr(Person,'func'))   #True

    ②getattr

    此方法是用来获取一个对象的XX,XX是字符串类型,它可以是类的属性,可以对象是属性及方法,可以是模块的类,等等……

    最好搭配hasattr方法使用,判断它有此方法或者对象的时候才获取,以免找不到报错,也可以指定找不到的默认值。格式为getattr(对象,XX,默认值),如下:

     1 class Person:
     2     kind = '人类'
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6         self.changdu = 28
     7     def func(self):
     8         print('func.....')
     9 p = Person('fuyong',18)
    10 
    11 ret = getattr(p,'func',None)
    12 if ret:
    13    ret()    #func.....
    14 
    15 ret = getattr(p,'funcxxx','没有此方法')
    16 print(ret)  #没有此方法
    17 
    18 if hasattr(p,'func'):
    19     getattr(p,'func')() #func.....

    ③setattr

    此方法用来设置一个对象的属性,格式为setattr(对象,属性名,属性值) ,如下:

     1 class Person:
     2     kind = '人类'
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6         self.changdu = 28
     7     def func(self):
     8         print('func.....')
     9 p = Person('fuyong',18)
    10 
    11 print(p.age)        #18
    12 setattr(p,'age',19)
    13 print(p.age)        #19
    14     

    ④delattr

    此方法是用来删除一个对象的属性,格式为delattr(对象,XXX) ,如下:

     1 class Person:
     2     kind = '人类'
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6         self.changdu = 28
     7     def func(self):
     8         print('func.....')
     9 p = Person('fuyong',18)
    10 
    11 print(p.age)        #18
    12 delattr(p,'age')
    13 print(p.age)        #报错:AttributeError: 'Person' object has no attribute 'age'

    三、类的内置方法

    ① __init__

    此方法在类被实例化的时候被自动调用

    ② __str__和__repr__

    __str__( )方法在三种情况下被自动调用

    △ str(对象名)

    △ print(对象名)

    △ '%s'%对象名

    如下:

     1 class Person:
     2     def __init__(self,name,age):
     3         self.name = name
     4         self.age = age
     5     def __str__(self):
     6         return '他是一个名叫%s的帅哥'%self.name
     7 
     8 p = Person('fuyong',18)
     9 print(str(p))           #他是一个名叫fuyong的帅哥
    10 print(p)                #他是一个名叫fuyong的帅哥
    11 print('%s'%p)           #他是一个名叫fuyong的帅哥

    __repr__方法在以下三种情况下被调用:

    △ repr(对象名)

    △ '%r'%对象名

    △ 当类没有__str__方法又被调用__str__方法的时候被调用

    如下:

     1 class Person:
     2     def __init__(self,name,age):
     3         self.name = name
     4         self.age = age
     5     def __repr__(self):
     6         return '他是一个名叫%s的帅哥'%self.name
     7 
     8 p = Person('fuyong',18)
     9 print(repr(p))
    10 print('%r'%p)
    11 print(str(p))
    12 print(p)
    13 #打印结果如下
    14 # 他是一个名叫fuyong的帅哥
    15 # 他是一个名叫fuyong的帅哥
    16 # 他是一个名叫fuyong的帅哥
    17 # 他是一个名叫fuyong的帅哥

    ③ __del__

    此方法会在对象被释放的时候被自动调用(一种情况是对象被删除,一种情况是程序执行完了被Python解释器释放),如下:

     1 class Person:
     2     def __init__(self,name,age):
     3         self.name = name
     4         self.age = age
     5     def __del__(self):
     6         print('程序执行完了')
     7 
     8 p = Person('fuyong',18)
     9 
    10 #程序执行完了

    ④ __call__

    此方法会在对象后面加括号的时候被自动调用,如下:

    1 class Person:
    2     def __init__(self,name,age):
    3         self.name = name
    4         self.age = age
    5     def __call__(self):
    6         print('你在对象名后加了括号(类似一个函数)')
    7 p = Person('fuyong',18)
    8 p()
    9 #你在对象名后加了括号(类似一个函数)

    ⑤ __len__

    此方法在调用len(对象)的时候被执行,如下:

    1 class Person:
    2     def __init__(self,name,age):
    3         self.name = name
    4         self.age = age
    5         self.changdu = 28
    6     def __len__(self):
    7         return self.changdu
    8 p = Person('fuyong',18)
    9 print(len(p)) #28

    ⑥ __new__

    此方法是在实例化一个对象的时候回自动触发(在__init__函数之前)。如下:

     1 class Person:
     2     def __init__(self,name):
     3         self.name = name
     4         print('调用__init__函数........')
     5 
     6     def __new__(cls, *args, **kwargs):
     7         print('调用__new__函数.........')
     8         return object.__new__(Person)
     9 
    10 p = Person('付勇')
    11 print(p.name)
    12 
    13 #调用__new__函数.........
    14 # 调用__init__函数........
    15 # 付勇

    利用__new__方法实现单例模式:

     1 class Person:
     2     _obj = None
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def __new__(cls, *args, **kwargs):
     7         if cls._obj:
     8             return _obj
     9         else:
    10             _obj = object.__new__(Person)
    11 
    12 p1 = Person('付勇')
    13 p2 = Person('小明')
    14 print(p1 is p2)

    ⑦ __hash__

    此方法在has(对象)的时候被调用,如下:

     1 class Person:
     2     _obj = None
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6 
     7     def __hash__(self):
     8         return hash(self.name)+hash(self.age)
     9 
    10 p1 = Person('付勇',18)
    11 p2 = Person('付勇',19)
    12 print(hash(p1) == hash(p2))         #False

    ⑧__eq__

    此方法在比较两个对象的时候被调用,如:obj1 == obj2  或者   如下:

     1 class Person:
     2     _obj = None
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6 
     7     def __eq__(self, other):
     8         if self.__dict__ == other.__dict__:
     9             return True
    10         else:
    11             return False
    12 
    13 p1 = Person('付勇',18)
    14 p2 = Person('付勇',18)
    15 print(p1 == p2)         #True

    ⑨ __getitem__\__setitem__\__delitem__

    一旦一个类中定义了这三种内置方法,操作类的属性的时候就可以像操作字典一样,如:

    obj [属性]                 ---->   __getitem__
    
    obj [属性] = 属性值         ----> __setitem__
    
    del obj [属性]             ---->  __delitem__

      实例如下:

     1 class Person:
     2     def __init__(self,name,age):
     3         self.name = name
     4         self.age = age
     5 
     6     def __getitem__(self, item):
     7         return self.__dict__[item]
     8 
     9     def __setitem__(self, key, value):
    10         self.__dict__[key] = value
    11 
    12     def __delitem__(self,key):
    13         del self.__dict__[key]
    14 
    15 p = Person('付勇',18)
    16 
    17 print(p['name'])      #付勇
    18 
    19 p['age'] = 19
    20 print(p['age'])      #19
    21 
    22 del p['age']
    23
    24 print(p['age'])     #因为age属性已被删除,所以会报错!KeyError: 'age'
  • 相关阅读:
    构建maven项目,自定义目录结构方法
    Nginx反向代理实现负载均衡以及session共享
    Spring Boot 2.x引入JS,CSS 失效问题
    WebMvcConfigurerAdapter已过时
    闲谈Tomcat性能优化
    oracle decode函数和 sign函数
    为什么要使用MQ和到底什么时候要使用MQ
    redis持久化的几种方式
    【mySQL】left join、right join和join的区别
    redis缓存在项目中的使用
  • 原文地址:https://www.cnblogs.com/fu-yong/p/8330979.html
Copyright © 2011-2022 走看看