热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python元类、反射及双线方法

元类print(type(abc))print(type(True))print(type(100))print(type([1,2,3]))print(type({na

元类

print(type('abc'))
print(type(True))
print(type(100))
print(type([1, 2, 3]))
print(type({'name': '太白金星'}))
print(type((1,2,3)))
print(type(object))class A:passprint(isinstance(object,type))
print(isinstance(A, type))

type元类是获取该对象从属于的类,而type类比较特殊,Python原则是:一切皆对象,其实类也可以理解为’对象’,而type元类又称作构建类,python中大多数内置的类(包括object)以及自己定义的类,都是由type元类创造的。

而type类与object类之间的关系比较独特:object是type类的实例,而type类是object类的子类,这种关系比较神奇无法使用python的代码表述,因为定义其中一个之前另一个必须存在。所以这个只作为了解。

反射

反射是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。

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

反射中常用的四个函数:

class Student:f = '类的静态变量'def __init__(self,name,age):self.name=nameself.age=agedef say_hi(self):print('hi,%s'%self.name)
obj=Student('alex',16)

hasatter 检测是否含有某属性,方法

print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))结果:
True
True

获取属性,方法 # 获取不到直接报错

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''

n=getattr(obj,'name')
print(n)
func=getattr(obj,'say_hi')
func()结果:
'alex'
'hi,alex'

设置属性

setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))结果:
{&#39;name&#39;: &#39;alex&#39;, &#39;age&#39;: 16, &#39;sb&#39;: True, &#39;show_name&#39;: <function <lambda> at 0x00000180E591BB70>}
alexsb

删除属性

delattr(obj,&#39;age&#39;)
# delattr(obj,&#39;show_name&#39;)
# delattr(obj,&#39;show_name111&#39;)#不存在,则报错print(obj.__dict__)结果&#xff1a;
{&#39;name&#39;: &#39;alex&#39;}

对类的反射&#xff1a;

&#39;&#39;&#39;
遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939
寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电子书&#xff01;
&#39;&#39;&#39;

class Foo(object):staticField &#61; "old boy"def __init__(self):self.name &#61; &#39;wupeiqi&#39;def func(self):return &#39;func&#39;&#64;staticmethoddef bar():return &#39;bar&#39;print(getattr(Foo, &#39;staticField&#39;))
print(getattr(Foo, &#39;func&#39;))
print(getattr(Foo, &#39;bar&#39;))
# 结果&#xff1a;
old boy
<function Foo.func at 0x00000212D21FBC80> # 获取func对象方法地址
<function Foo.bar at 0x00000212D21FBD08> # 获取bar静态方法地址

对当前模块的反射&#xff1a;

import sysdef s1():print(&#39;s1&#39;)def s2():print(&#39;s2&#39;) this_module &#61; sys.modules[__name__]print(hasattr(this_module, &#39;s1&#39;))
print(getattr(this_module, &#39;s2&#39;))# 结果&#xff1a;
True
<function s2 at 0x000002000247BBF8>

对其他模块的反射&#xff1a;

import time
print(hasattr(time,&#39;ctime&#39;))
print(getattr(time,&#39;ctime&#39;))
print(getattr(time,&#39;ctime&#39;)())# 结果&#xff1a;
True
<built-in function ctime>
&#39;Fri Aug 9 08:12:54 2019&#39;

反射的应用

# 没学反射之前的解决方式:
class User:def login(self):print(&#39;欢迎来到登录页面&#39;)def register(self):print(&#39;欢迎来到注册页面&#39;)def save(self):print(&#39;欢迎来到存储页面&#39;)while 1:choose &#61; input(&#39;>>>&#39;).strip()if choose &#61;&#61; &#39;login&#39;:obj &#61; User()obj.login()elif choose &#61;&#61; &#39;register&#39;:obj &#61; User()obj.register()elif choose &#61;&#61; &#39;save&#39;:obj &#61; User()obj.save()# 学了反射之后解决方式
class User:def login(self):print(&#39;欢迎来到登录页面&#39;)def register(self):print(&#39;欢迎来到注册页面&#39;)def save(self):print(&#39;欢迎来到存储页面&#39;)user &#61; User()
while 1:choose &#61; input(&#39;>>>&#39;).strip()if hasattr(user,choose):func &#61; getattr(user,choose)func()else:print(&#39;输入错误。。。。&#39;)

函数和方法的区别

通过打印函数(方法)名确定

&#39;&#39;&#39;
遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939
寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电子书&#xff01;
&#39;&#39;&#39;

def func():passprint(func) # class A:def func(self):passprint(A.func) #
obj &#61; A()
print(obj.func) # >

通过types模块验证

from types import FunctionType
from types import MethodTypedef func():passclass A:def func(self):passobj &#61; A()
print(isinstance(func,FunctionType)) # True
print(isinstance(A.func,FunctionType)) # True
print(isinstance(obj.func,FunctionType)) # False
print(isinstance(obj.func,MethodType)) # True

静态方法是函数

&#39;&#39;&#39;
遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939
寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电子书&#xff01;
&#39;&#39;&#39;

from types import FunctionType
from types import MethodTypeclass A:def func(self):pass &#64;classmethoddef func1(self):pass &#64;staticmethoddef func2(self):pass
obj &#61; A()# 静态方法其实是函数
print(isinstance(A.func2,FunctionType)) # True
print(isinstance(obj.func2,FunctionType)) # True

函数和方法的几点区别&#xff1a;

&#xff08;1&#xff09;函数的是显性传参的&#xff0c;方法是隐性传参的。

&#xff08;2&#xff09;函数则跟对象无关。

&#xff08;3&#xff09;方法可以操作类内部的数据。

&#xff08;4&#xff09;方法跟对象是关联的。

双线方法

定义&#xff1a;双下方法是特殊方法&#xff0c;他是解释器提供的 由双下划线加方法名加双下划线 __方法名__的具有特殊意义的方法,双下方法主要是python源码程序员使用的&#xff0c;在开发中尽量不要使用双下方法&#xff0c;熟知双下划线方法有助于我们研究源码

1、__len__

class B:def __len__(self):print(666)b &#61; B()
len(b) # len 一个对象就会触发 __len__方法。class A:def __init__(self):self.a &#61; 1self.b &#61; 2def __len__(self):return len(self.__dict__)
a &#61; A()
print(len(a))

2、_hash_

&#39;&#39;&#39;
遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939
寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电子书&#xff01;
&#39;&#39;&#39;

class A:def __init__(self):self.a &#61; 1self.b &#61; 2def __hash__(self):return hash(str(self.a)&#43;str(self.b))
a &#61; A()
print(hash(a))

3、_str_

如果一个类中定义了__str__方法&#xff0c;那么在打印 对象 时&#xff0c;默认输出该方法的返回值。

class A:def __init__(self):passdef __str__(self):return &#39;太白&#39;
a &#61; A()
print(a)
print(&#39;%s&#39; % a)

4、_repr_

如果一个类中定义了__repr__方法&#xff0c;那么在repr(对象) 时&#xff0c;默认输出该方法的返回值。

class A:def __init__(self):passdef __repr__(self):return &#39;太白&#39;
a &#61; A()
print(repr(a))
print(&#39;%r&#39;%a)

5、_call_

对象后面加括号&#xff0c;触发执行。

注&#xff1a;构造方法__new__的执行是由创建对象触发的&#xff0c;即&#xff1a;对象 &#61; 类名() &#xff1b;而对于 call 方法的执行是由对象后加括号触发的&#xff0c;即&#xff1a;对象() 或者 类()()

&#39;&#39;&#39;
遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939
寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电子书&#xff01;
&#39;&#39;&#39;

class Foo:def __init__(self):passdef __call__(self, *args, **kwargs):print(&#39;__call__&#39;)obj &#61; Foo() # 执行 __init__
obj() # 执行 __call__

6、_eq_

class A:def __init__(self):self.a &#61; 1self.b &#61; 2def __eq__(self,obj):if self.a &#61;&#61; obj.a and self.b &#61;&#61; obj.b:return True
a &#61; A()
b &#61; A()
print(a &#61;&#61; b)

7、_del_

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

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

class A:def __init__(self):self.x &#61; 1print(&#39;in init function&#39;)def __new__(cls, *args, **kwargs):print(&#39;in new function&#39;)return object.__new__(A, *args, **kwargs)a &#61; A()
print(a.x)

8、_new_

class A:def __init__(self):self.x &#61; 1print(&#39;in init function&#39;)def __new__(cls, *args, **kwargs):print(&#39;in new function&#39;)return object.__new__(A, *args, **kwargs)a &#61; A()
print(a.x)

单例模式&#xff1a;

&#39;&#39;&#39;
遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939
寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电子书&#xff01;
&#39;&#39;&#39;

class A:__instance &#61; Nonedef __new__(cls, *args, **kwargs):if cls.__instance is None:obj &#61; object.__new__(cls)cls.__instance &#61; objreturn cls.__instance

9、 __item__系列

class Foo:def __init__(self,name):self.name&#61;namedef __getitem__(self, item):print(self.__dict__[item])def __setitem__(self, key, value):self.__dict__[key]&#61;valuedef __delitem__(self, key):print(&#39;del obj[key]时,我执行&#39;)self.__dict__.pop(key)def __delattr__(self, item):print(&#39;del obj.key时,我执行&#39;)self.__dict__.pop(item)f1&#61;Foo(&#39;sb&#39;)
f1[&#39;age&#39;]&#61;18
f1[&#39;age1&#39;]&#61;19
del f1.age1
del f1[&#39;age&#39;]
f1[&#39;name&#39;]&#61;&#39;alex&#39;
print(f1.__dict__)

10 上下文管理器相关

__enter__ __exit__

# 如果想要对一个类的对象进行with as 的操作 不行。
class A:def __init__(self, text):self.text &#61; textwith A(&#39;大爷&#39;) as f1:print(f1.text)class A:def __init__(self, text):self.text &#61; textdef __enter__(self): # 开启上下文管理器对象时触发此方法self.text &#61; self.text &#43; &#39;您来啦&#39;return self # 将实例化的对象返回f1def __exit__(self, exc_type, exc_val, exc_tb): # 执行完上下文管理器对象f1时触发此方法self.text &#61; self.text &#43; &#39;这就走啦&#39;with A(&#39;大爷&#39;) as f1:print(f1.text)
print(f1.text)

自定义文件管理器

&#39;&#39;&#39;
遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939
寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电子书&#xff01;
&#39;&#39;&#39;

class Diycontextor:def __init__(self,name,mode):self.name &#61; nameself.mode &#61; modedef __enter__(self):print("Hi enter here!!")self.filehander &#61; open(self.name,self.mode)return self.filehanderdef __exit__(self,*para):print("Hi exit here")self.filehander.close()with Diycontextor(&#39;py_ana.py&#39;,&#39;r&#39;) as f:for i in f:print(i)

推荐阅读
author-avatar
李桂平2402851397
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有