反射 函数vs方法 特殊的双下方法  

一丶反射

什么是反射:

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

Python面向对象的反射:

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

####  四个实现反射的函数
# hasattr(), getattr(), setattr(), delattr()
   

#### 反射 整合版
class Foo:
   public_attr='静态属性'

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

   def func(self):
       print('Hello Python')


obj=Foo('张三',18) # 实例化对象


## 检测是否含有XX属性
print(hasattr(obj,'public_attr'))   #当前实例对象,是否含有静态变量public_attr
print(hasattr(obj,'func'))          #当前实例对象,是否含有func方法



## 获取属性 getattr(对象,字符串,None)
print(getattr(obj,'public_attr'),None)   #静态属性,不存在就返回None
print(getattr(obj,'func'))  # <bound method Foo.func of <__main__.Foo object at 0x0000015FF30EC8D0>>



## 设置属性 setattr(对象,字符串,值)
setattr(obj,'sex','男')  # 设置对象属性
print(obj.__dict__) # {'name': '张三', 'age': 18, 'sex': '男'}

## 设置匿名方法 self为参数
setattr(obj,'show_name',lambda self:self.name)
print(obj.show_name(obj))   # 设置方法,
print(obj.__dict__)# { 'show_name': <function <lambda> at 0x0000018512932EA0>}



## 删除属性
delattr(obj,'name')
delattr(obj,'name')    # 不存在就报错
print(obj.__dict__) # {'age': 18, 'sex': '男', 'show_name': <function <lambda> at 0x000001D901BE2EA0>}




###  从当前 脚本(本类) 研究反射

class B:
   sta_='abc'


def func1():
   print('in func1')

import sys
this_module=sys.modules[__name__]  # 获取py文件对象
print(this_module) # 这是一个对象 <module '__main__' from 'E:/File/oldboy学习笔记/Python之路/day26/01 反射.py'>

print(hasattr(this_module,'func1')) # 判断函数名属性 存在不存在, True
print(getattr(this_module,'func1')) # 获得函数名属性 <function func1 at 0x00000225EBA92EA0>

getattr(this_module,'func1')()   #获得函数名属性+()执行func1函数

print(hasattr(this_module,'B')) # 判断类名属性 存在不存在 True
print(getattr(this_module,'B')) # 获得类名属性打印 <class '__main__.B'>
cls=getattr(this_module,'B')    # cls 得到是一个B类的地址
print(cls)                      # <class '__main__.B'>
obj=cls()                       # cls+() 实例化一个对象
print(obj.sta_)                 # obj对象.B对象中的静态属性

案例:

class Auth:
   funcli=[('login','请登录'),('register','请注册'),('exit','退出')]
   def login(self):
       print('登录函数')


   def register(self):
       print('注册函数')


   def exit(self):
       print('退出...')


while 1:
   obj=Auth()

   for num , option in enumerate(obj.funcli,1):
       print(num,option[0],option[1])

   func_name = input('请输入选择:').strip()
   if hasattr(obj,obj.funcli[int(func_name)-1][0]):
       getattr(obj,obj.funcli[int(func_name)-1][0],'不存在')()

 

二丶函数vs方法

函数和方法有什么区别和相同之处?

函数是显性传参, 方法是隐性传参

####  通过打印函数名确定

   def func():
       pass

   print(func)  # 函数 <function func at 0x00000260A2E690D0>


   class A:
       def func(self):
           pass

   print(A.func)  # 函数 <function A.func at 0x0000026E65AE9C80>
   obj = A()
   print(obj.func)  # 方法 <bound method A.func of <__main__.A object at 0x00000230BAD4C9E8>>




#### 通过types模块验证
   from types import FunctionType # 函数
   from types import MethodType # 方法

   def func():
       pass


   class A:
       def func(self):
           pass

   obj = A()

## isinstance(obj,M) 判断 obj对象 ,是不是由M类 或 M类的派生类 实例化的对象
   print(isinstance(func,FunctionType)) # True 函数
   print(isinstance(A.func,FunctionType)) # True   类调用类中的func 是函数
   print(isinstance(obj.func,FunctionType)) # False   实例对象调用 不是函数
   print(isinstance(obj.func,MethodType)) # True   实例对象调用 是方法

研究类中的三个特殊的方法(静态方法,类方法,属性)

####  类中的静态方法是函数(静态函数)
   from types import FunctionType
   from types import MethodType

   class A:

       def func(self):
           pass

       @classmethod
       def func1(self):
           pass

       @staticmethod
       def func2(self):
           pass
   obj = A()

   # 静态方法其实是函数
   print(isinstance(A.func2,FunctionType))  # True
   print(isinstance(obj.func2,FunctionType))  # True

   
 



#### 类中的类方法是方法(类方法)
   from types import FunctionType
   from types import MethodType

   class A:
       
       @classmethod
       def paas(cls):
           pass
       
       @property
       def a(self):
           pass
   obj=A()


   #   类方法 类和对象 调用 都是方法
   print(isinstance(obj.paas,FunctionType))    # False
   print(isinstance(obj.paas,MethodType))      # True

   print(isinstance(A.paas,FunctionType))      # False
   print(isinstance(A.paas,MethodType))        # True

   




#### 类中的属性伪装函数 . 什么也不是,单纯的伪装属性

   from types import FunctionType
   from types import MethodType

   class A:
       
       @classmethod
       def paas(cls): # 类方法是 cls, 实例对象或类调用.默认将从属的类地址传给cls (隐性传参)
           pass
       
       @property
       def a(self):
           pass
       
   obj=A() # 实例化对象

   # 属性 ,     类和对象 调用 什么都不是
   print(isinstance(obj.a,FunctionType))    # False
   print(isinstance(obj.a,MethodType))      # False

   print(isinstance(A.a,FunctionType))      # False
   print(isinstance(A.a,MethodType))        # False