博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python学习【第14篇】:面向对象之反射以及内置方法
阅读量:6573 次
发布时间:2019-06-24

本文共 8714 字,大约阅读时间需要 29 分钟。

一、静态方法(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()#类名.方法名()
复制代码

一、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)
复制代码
1 delattr(egg,'name')2 print(egg.name)

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('没找到')
复制代码

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()
复制代码

3.模块应用反射

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

复制代码
1 # 1.导入其他模块引用2 import mymodule3 print(hasattr(mymodule,'test'))4 getattr(mymodule,'test')()5 6 # # 这里的getattr(mymodule,'test')()这一句相当于7 # p = getattr(mymodule,'test')8 # p()
复制代码
复制代码
1 # 2.在本模块中应用反射2 def demo1():3     print('wwww')4 import sys5 # 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')()
复制代码
复制代码
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)()
复制代码

反射补充:

db.mysql

class MySQlHelper(object):    print('MySQlHelper1111111')    def fetchone(self):        print('你好')

db.pool

class PoolHelper(object):    print('PoolHelper')

settings.py

复制代码
DB_PATH = 'db.mysql.MySQlHelper'#吧字符串切割module_name,cls_name = DB_PATH.rsplit('.',maxsplit=1)# print(module_name,cls_name)  #db.mysql    MySQlHelper#导入模块# from db.mysql import MySQlHelperimport importlibmoudel_obj = importlib.import_module(module_name)print(moudel_obj,type(moudel_obj))#导入模块中的类cls = getattr(moudel_obj,cls_name)print(cls) #对类进行实例化 obj = cls() obj.fetchone() # 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__
复制代码

 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 12311     def __setitem__(self, key, value):  #修改12         print(key,value)13         self.__dict__[key] = value14     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])
复制代码

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)
复制代码
复制代码
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)
复制代码

5.__call__

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

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

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

6.__len__

__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方法是可以重写的
复制代码

8.__eq__

复制代码
1 class A:2     def __eq__(self, other):3         return True4 a = A()5 b = A()6 print(a==b) #不加方法的时候返回的是False,加了个__eq__方法就返回了个True7 # '=='内部就调用了__eq__方法8 print(a is b)
复制代码

 一道面试题

面试题
复制代码
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])
复制代码

 

转载于:https://www.cnblogs.com/kcwxx/p/10145181.html

你可能感兴趣的文章
Java Volatile关键字 以及long,double在多线程中的应用
查看>>
__slots__用法以及优化
查看>>
分部积分的图形解释
查看>>
idea常用快捷键大全(转)
查看>>
HashMap和Hashtable的区别 源码分析
查看>>
Git初始化仓库
查看>>
mysql利用timestamp来进行帖子排序
查看>>
SQL Server 管理常用的SQL和T-SQL
查看>>
Microsoft Orleans 之 入门指南
查看>>
MySoft.Data 2.7.3版本的GitHub托管(ORM升级封装)
查看>>
eclipse各版本代号
查看>>
mysql 配置 utf8 依然乱码
查看>>
089实战 Nginx的安装
查看>>
Laravel 使用多个数据库的问题。
查看>>
overridePendingTransition简介
查看>>
7 -- Spring的基本用法 -- 5... Spring容器中的Bean;容器中Bean的作用域;配置依赖;...
查看>>
Ubuntu开机自启动
查看>>
iOS程序启动原理
查看>>
HTTP协议 - 协议格式
查看>>
PHP实反向代理-收藏
查看>>