面向对象之反射及内置方法

Posted lz1996

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象之反射及内置方法相关的知识,希望对你有一定的参考价值。

一、静态方法(staticmethod)和类方法(classmethod)

类方法:有个默认参数cls,并且可以直接用类名去调用,可以与类属性交互(也就是可以使用类属性)

    静态方法:让类里的方法直接被类调用,就像正常调用函数一样

    类方法和静态方法的相同点:都可以直接被类调用,不需要实例化

  类方法和静态方法的不同点:类方法必须有一个cls参数表示这个类,可以使用类属性静态方法不需要参数

  绑定方法:分为普通方法和类方法

   普通方法:默认有一个self对象传进来,并且只能被对象调用-------绑定到对象

   类方法:默认有一个cls对象传进来,并且可以被类和对象(不推荐)调用-----绑定到类

  非绑定方法:静态方法:没有设置默认参数,并且可以被类和对象(不推荐)调用-----非绑定

技术图片
  1 class Student:
  2     f = open(‘student‘, encoding=‘utf-8‘)
  3     def __init__(self):
  4         pass
  5     @classmethod #类方法 :有个默认参数cls,并且可以直接使用类名去
  6                  #调用,还可以与类属性交互(也就是可以使用类属性)
  7     def show_student_info_class(cls):
  8         # f = open(‘student‘, encoding=‘utf-8‘)
  9         for line in cls.f:
 10             name,sex = line.strip().split(‘,‘)
 11             print(name,sex)
 12     @staticmethod  #静态方法:可以直接使用类名去调用,就像正常的函数调用一样
 13     def show_student_info_static(): #不用传self
 14         f = open(‘student‘,encoding=‘utf-8‘)
 15         for line in f:
 16             name,sex = line.strip().split(‘,‘)
 17             print(name,sex)
 18 # egon = Student()
 19 # egon.show_student_info_static()  #也可以这样调,但是还是推荐用类名去调
 20 # egon.show_student_info_class()
 21 
 22 Student.show_student_info_class()#类名.方法名()
 23 print(‘-------------------‘)
 24 Student.show_student_info_static()#类名.方法名()
 25 
 26 staticmethod和classmethod
staticmethod和classmethod

一、isinstance 和 issubclass

    isinstance(obj,cls):检查obj是不是cls的对象(传两个参数,一个是对象,一个是类)

    issubclass(sub,super):检查sub是不是super的子类(传两个参数,一个是子类,一个是父类)

技术图片
  1 class Foo:
  2     pass
  3 class Son(Foo):
  4     pass
  5 s = Son()
  6 print(isinstance(s,Son))  #判断s是不是Son的对象
  7 print(type(s) is Son)
  8 print(isinstance(s,Foo))  #判断s是不是Foo的对象  不精准
  9 print(type(s) is Foo)  #type比较精准
 10 
 11 print(issubclass(Son,Foo)) #判断Son是不是Foo的子类
 12 print(issubclass(Son,object))
 13 print(issubclass(Foo,object))
 14 print(issubclass(int,object))

二、反射

    反射:可以用字符串的方式去访问对象的属性,调用对象的方法(但是不能去访问方法),python中一切皆对象,都可以使用反射。

    反射有四种方法:

      hasattr:hasattr(object,name)判断一个对象是否有name属性或者name方法。有就返回True,没有就返回False

      getattr:获取对象的属性或者方法,如果存在则打印出来。hasattr和getattr配套使用

 需要注意的是,如果返回的是对象的方法,返回出来的是对象的内存地址,如果需要运行这个方法,可以在后面添加一对()

    setattr:给对象的属性赋值,若属性不存在,先创建后赋值

    delattr:删除该对象指定的一个属性

技术图片
  1 class Foo:
  2     def __init__(self):
  3         self.name = ‘egon‘
  4         self.age = 51
  5     def func(self):
  6         print(‘hello‘)
  7 egg = Foo()
  8 setattr(egg,‘sex‘,‘男‘)
  9 print(egg.sex)
 10 # 2.
 11 def show_name(self):
 12     print(self.name+‘sb‘)
 13 setattr(egg,‘sh_name‘,show_name)
 14 egg.sh_name(egg)
 15 show_name(egg)
 16 
 17 setattr
setattr

 

技术图片
  1 delattr(egg,‘name‘)
  2 print(egg.name)
delattr

1.对象应用反射

技术图片
  1 class Foo:
  2     def __init__(self):
  3         self.name = ‘egon‘
  4         self.age = 51
  5     def func(self):
  6         print(‘hello‘)
  7 egg = Foo()
  8 print(hasattr(egg,‘name‘))  #先判断name在egg里面存在不存在
  9 print(getattr(egg,‘name‘)) #如果为True它才去得到
 10 print(hasattr(egg,‘func‘))
 11 print(getattr(egg,‘func‘))  #得到的是地址
 12 # getattr(egg,‘func‘)()  #在这里加括号才能得到,因为func是方法
 13 if hasattr(egg,‘func‘):
 14     getattr(egg,‘func‘)()
 15 else:
 16     print(‘没找到‘)
 17 
 18 对象应用反射
对象应用反射

2.类应用反射

技术图片
  1 class Foo:
  2     f = 123
  3     @classmethod
  4     def class_method_dome(cls):
  5         print(‘class_method_dome‘)
  6 
  7     @staticmethod
  8     def static_method_dome():
  9         print(‘static_method_dome‘)
 10 print(hasattr(Foo,‘class_method_dome‘))
 11 method = getattr(Foo,‘class_method_dome‘)
 12 method()
 13 print(‘------------‘)
 14 print(hasattr(Foo,‘static_method_dome‘))
 15 method1 = getattr(Foo,‘static_method_dome‘)
 16 method1()
 17 
 18 类应用反射
类应用反射

3.模块应用反射

    模块的应用又分为导入其他模块反射和在本模块中反射

技术图片
  1 # 1.导入其他模块引用
  2 import mymodule
  3 print(hasattr(mymodule,‘test‘))
  4 getattr(mymodule,‘test‘)()
  5 
  6 # # 这里的getattr(mymodule,‘test‘)()这一句相当于
  7 # p = getattr(mymodule,‘test‘)
  8 # p()
  9 
 10 导入其他模块反射
导入其他模块反射

 

技术图片
  1 # 2.在本模块中应用反射
  2 def demo1():
  3     print(‘wwww‘)
  4 import sys
  5 # print(sys.modules)
  6 module_obj = sys.modules[__name__]  #相当于‘__main__  7 print(module_obj)
  8 print(hasattr(module_obj,‘demo1‘))
  9 getattr(module_obj,‘demo1‘)()
 10 
 11 在本模块中应用反射
在本模块中应用反射

 

技术图片
  1 # 举例
  2 def 注册():
  3     print(‘regiester‘)
  4 def 登录():
  5     print(‘login‘)
  6 def 购物():
  7     pass
  8 print(‘注册,登录,购物‘)
  9 ret = input(‘请输入你要做的操作:‘)
 10 import sys
 11 my_module = sys.modules[__name__]  #利用sys模块导入一个自己的模块
 12 if hasattr(my_module,ret):
 13     getattr(my_module,ret)()
 14 
 15 导入自己的模块的一个简单小例子
导入自己的模块的一个简单小例子

反射补充:

db.mysql

  1 class MySQlHelper(object):
  2     print(‘MySQlHelper1111111‘)
  3     def fetchone(self):
  4         print(‘你好‘)

db.pool

  1 class PoolHelper(object):
  2     print(‘PoolHelper‘)

settings.py

技术图片
  1 DB_PATH = ‘db.mysql.MySQlHelper‘
  2 
  3 #吧字符串切割
  4 module_name,cls_name = DB_PATH.rsplit(‘.‘,maxsplit=1)
  5 # print(module_name,cls_name)  #db.mysql    MySQlHelper
  6 #导入模块
  7 # from db.mysql import MySQlHelper
  8 import importlib
  9 moudel_obj = importlib.import_module(module_name)
 10 print(moudel_obj,type(moudel_obj))
 11 #导入模块中的类
 12 cls = getattr(moudel_obj,cls_name)
 13 print(cls)
 14 #对类进行实例化
 15 obj = cls()
 16 obj.fetchone()
 17 # getattr()

三、内置方法

1.__str__和__repr__

改变对象的字符串显示

技术图片
  1 class Foo:
  2     def __init__(self,name):
  3         self.name = name
  4     def __repr__(self):
  5         return ‘obj in str‘  #这里只能是return
  6     # def __str__(self):
  7     #     return ‘%s obj in str‘%self.name
  8 f = Foo(‘egon‘)
  9 print(f)  #优先执行__str__里面的内容
 10 # 那么你是不是据地__repr__没用呢?
 11 # print(‘%s‘%f)  #执行的是__str__里面的返回值
 12 # print(‘%r‘%f)  #执行的是__repr__里面的返回值
 13 print(‘==============‘)
 14 print(str(f))  #当执行str(f)时,会去找__str__这个方法,如果找不到的时候,__repr__这个方法就给替补了
 15 print(repr(f))
 16 #1.当打印一个对象的时候,如果实现了__str__方法,打印__str__中的返回值
 17 # 2.当__str__没有被实现的时候,就会调用__repr__方法
 18 # 3.但是当你用字符串格式化的时候,%s和%r会分别调用__str__和__repr__方法
 19 # 4.不管是在字符串格式化的时候还是在打印对象的时候,
 20 # __repr__方法都可以作为__str__方法的替补,但反之则不行
 21 # 5.用于友好的表示对象。如果__str__和__repr__方法你只能实现一个:先实现__repr__
 22 
 23  __str__和__repr__
__str__和__repr__

2.__del__

析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

技术图片
  1 class Foo:
  2     def __del__(self):
  3         print(‘执行我啦‘)
  4 
  5 f= Foo()
  6 print(123)
  7 print(123)
  8 print(123)
  9 print(123)

3.item系列

分别有__getitem__      ,__setitem__    ,__delitem__

技术图片
  1 class Foo:
  2     def __init__(self):
  3         self.name = ‘egon‘
  4         self.age = 73
  5         self.l=[1,2,3]
  6     def __getitem__(self, item):  #得到
  7         # return  self.l[item]
  8         # return self.__dict__[item]
  9         # print(Foo.__dict__)
 10         return 123
 11     def __setitem__(self, key, value):  #修改
 12         print(key,value)
 13         self.__dict__[key] = value
 14     def __delitem__(self, key):  #删除
 15         del self.__dict__[key]
 16 f = Foo()
 17 print(f[‘qqq‘])  #不管里面放的啥值,它都会得到返回值的内容,调用的是__getitem__方法
 18 f[‘name‘]=‘alex‘ #修改egon的值为alex,调用 __setitem__方法
 19 # del f[‘name‘] #删除name,就会报错了,说明在调用__delitem__方法调用成功了,就已经删了,就会报错了
 20 print(f.name)
 21 f1 = Foo()
 22 print(f == f1)
 23 # print(f.name)
 24 # print(f[0])  #一开始不能这样取值,但是提供了一个__getitem__方法,这样就可以用了
 25 # print(f[1])
 26 # print(f[2])
 27 
 28 三个方法的使用
三个方法的使用

4.__new__(创建)

技术图片
  1 # 4.__new__方法
  2 # 单例模式:是一种设计模式
  3 class Singleton:
  4     def __new__(cls, *args, **kw):
  5         if not hasattr(cls, ‘_instance‘):
  6             orig = super(Singleton, cls)
  7             cls._instance = orig.__new__(cls, *args, **kw)
  8         return cls._instance
  9 
 10 one = Singleton()
 11 two = Singleton()
 12 print(one,two)   #他们两个的地址一样
 13 
 14 one.name = ‘alex‘
 15 print(two.name)
 16 
 17 单例模式
单例模式

 

技术图片
  1 # class A:
  2 #     def __init__(self):  #有一个方法在帮你创造self
  3 #         print(‘in init function‘)
  4 #         self.x = 1
  5 #
  6 #     def __new__(cls, *args, **kwargs):
  7 #         print(‘in new function‘)
  8 #         return object.__new__(A, *args, **kwargs)
  9 # a = A()
 10 # b = A()
 11 # c = A()
 12 # d = A()
 13 # print(a,b,c,d)
 14 
 15 __new__
__new__

 

5.__call__

对象后面加括号,触发执行

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

技术图片
  1 class Foo:
  2      def __call__(self, *args, **kwargs):
  3          print(123)
  4  # f = Foo()
  5  # f() #如果不写上面的__call__方法,就不会调用。如果加上,就正确了
  6  Foo()() #也可以这样表示
__call__

6.__len__

 

7.__hash__

技术图片
  1 class Foo:
  2     def __hash__(self):
  3         print(‘aaaaaaaaaa‘)
  4         return hash(self.name)
  5         # print(‘aaas‘)
  6 f = Foo()
  7 f.name = ‘egon‘
  8 print(hash(f))  #hash方法是可以重写的
  9 
 10 __hash__
__hash__

8.__eq__

技术图片
  1 class A:
  2     def __eq__(self, other):
  3         return True
  4 a = A()
  5 b = A()
  6 print(a==b) #不加方法的时候返回的是False,加了个__eq__方法就返回了个True
  7 # ‘==‘内部就调用了__eq__方法
  8 print(a is b)
  9 
 10 __eq__
__eq__

一道面试题

技术图片
  1 from collections import namedtuple
  2 Card = namedtuple(‘Card‘,[‘rank‘,‘suit‘])  #两个属性:一个是数,一个是花色(每一个card的对象就是一张纸牌)
  3 class FranchDeck: #纸牌数据类型
  4     ranks = [str(n) for n in range(2,11)] + list(‘JQKA‘)
  5     suits = [‘红心‘,‘方板‘,‘梅花‘,‘黑桃‘]
  6 
  7     def __init__(self):
  8         self._cards = [Card(rank,suit) for rank in FranchDeck.ranks #先循环这个,在循环下面的那个循环
  9                                         for suit in FranchDeck.suits]
 10 
 11     def __len__(self):
 12         return len(self._cards)
 13 
 14     def __getitem__(self, item):
 15         return self._cards[item]
 16 
 17     def __setitem__(self, key, value):
 18         self._cards[key] = value
 19 
 20 deck = FranchDeck()
 21 # print(deck[0])
 22 # print(deck[0])
 23 # print(deck[0])
 24 # print(deck[0])
 25 from random import choice
 26 print(choice(deck))
 27 print(choice(deck))
 28 
 29 from random import shuffle
 30 shuffle(deck)
 31 print(deck[:5])
 32 
 33 纸牌游戏
纸牌游戏

以上是关于面向对象之反射及内置方法的主要内容,如果未能解决你的问题,请参考以下文章

面向对象之反射及内置方法

Python学习第14篇:面向对象之反射以及内置方法

面向对象之 元类 , 反射 , 双下方法

第三十四篇 Python面向对象之 反射(自省)

面向对象的进阶---反射--一些内置方法

面向对象:反射内置方法