反射

反射主要用在网络编程中,

python面向对象的反射:通过字符串的形式操作对象相关的属性.python的一切事物都是对象.

反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!

getattr()

查找getattr(object,name[,default]):使用字符串数据类型获取对象的方法和属性,注意name是字符串,如果存在则返回,不存在则打印出默认值,默认值可选。需要注意的是如果要运行这个对象的方法,则需要加括号。

class Manegeemnt:
def __init__(self,name,sex,phone,mail):
self.name=name
self.sex=sex
self.phone=phone
self.mail=mail def creat_class(self):
print("创建了一条班级信息") maneger=Manegeemnt("小雨","女","","xiaoyu@163.com")
func=getattr(maneger,"name") #使用字符串的数据类型的变量名获取属性值。
print(func)

func=getattr(maneger,"creat_class")#得到的是方法的内存地址
func()
func=getattr(maneger,"mails","没有这条信息")
print(func)

结果:

小雨
创建了一条班级信息
没有这条信息

hasattr()

检查 hasattr(object,name[,default]):判断类中是否有这个属性如果存在返回True,否则False,在进行getattr前先判断有没有这个属性。一般他俩配合着使用。不要用try来替换它,我们能尽量少用try就少用,

多用些代码的方式来解决异常处理。

class Manegeemnt:
def __init__(self,name,sex,phone,mail):
self.name=name
self.sex=sex
self.phone=phone
self.mail=mail def creat_class(self):
print("创建了一条班级信息")
import logging
maneger=Manegeemnt("小雨","女","","xiaoyu@163.com")
if hasattr(maneger,"sex1"):
func=getattr(maneger,"sex1")
print(func)
else:
logging.warning("没有这条信息")

结果:

WARNING:root:没有这条信息

setattr()

设置 setattr(obj,变量名,值):对对象设置属性,添加属性。还可以添加方法不过这个方法不常用,

class A:
age=18
def __init__(self,name):
self.name=name
def walk(self):
print("walking")
a=A("小明") setattr(a,"country","中国")
print(a.country)

结果:

中国

delattr()

删除 delattr(obj,变量名)

class Manegeemnt:
def __init__(self,name,sex,phone,mail):
self.name=name
self.sex=sex
self.phone=phone
self.mail=mail def creat_class(self):
print("创建了一条班级信息")
import logging
maneger=Manegeemnt("小雨","女","","xiaoyu@163.com") setattr(Manegeemnt,"country","china")
print(Manegeemnt.country)

结果:

china

在sys.modules 里,如果我要运行当前的模块,那么当前的模块的名字就是__main__,所以可以跟筠模块名在sys.modules中得到他的模块对象、

a="bbb"
import sys
y=getattr(sys.modules["__main__"],"a") #利用模块名得到模块对象,注意在sys.modules 中的键是模块名,键值是模块对象。
print(y)

结果

bbb

另一种情况,如果我把上边的这个代码,剪贴到另外一个模块中,然后从本模块中导入,这时候再运行就会出错了,因为当前运行的程序名字中没有这段代码了,就不能用__main__,了,应该改为__name__.

范例:

a="bbb"
import sys
y=getattr(sys.modules[__name__],"a") #注意这里的__name__不能加引号,就是不能写成字符串,它的意思就是代表了这个程序的文件名。
print(y)

模块的反射

demo.py

def demo():
print("这是demo模块中的demo函数")

main.py

import demo
ret=getattr(demo,"demo")
ret()

应用场景:在django的CBV的源码中,在请求到了dispatch方法中是,基于反射根据请求方式的不同去调用不同的请求方法(比如post,get,put)

    def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)

item系列

__setitem__  ,
__getitem__
__delitem__

在类中, 只能用字典的方式,赋值,取值,删除值,才会调用响应的函数,用类自己的方法来,赋值,取值,删除值,不生效.

class A:
def __init__(self):
print("init.....")
def __setitem__(self, key, value):
print("set....")
def __getitem__(self, item):
print("get....")
def __delitem__(self, key):
print("del....")
b=A() #调用init函数
b["f"]=3 #调用set函数
b["f"] #调用get函数
del b["f"] #调用delete函数

结果:

init.....
set....
get....
del....

范例二:

lass testsetandget:
kk = {}
def __getitem__(self, key):
return self.kk[key] def __setitem__(self, key, value):
self.kk[key] = value
print("")
a=testsetandget()
a["first"]=1
print(a.kk)
a.__setitem__("你好",2)
a.__getitem__("你好")

结果:

1111
{'first': 1}
1111

面向对象内置函数

1. issubclass(子类,父类) 判断一个类是不是另一个类的父类

class A:
pass
class B(A):
pass print(issubclass(B,A))

结果:

True

2.isinstance(对象,已知类型) ,判断这个对象是不是已知类型

范例一:判断这个对象是不是A类实例化出来

class A:
pass
class B(A):
pass
c=B()
print(isinstance(c,A))

结果:

True

范例二判断这个变量是不是字符串?

f="fdfd"
print(isinstance(f,str))

结果:

True

__getattr__和__setattr__

__getattr__(self,item)

__getattr__(self,item) :拦截点号运算。当对象(注意不能是类,类会报错)对未定义的属性名称(只能是属性不能是方法,虽然调用方法时会调用该方法,但是程序也会报错)点号运算时,就会用属性名作为字符串调用这个方法,其中item就是调用的属性名称字符串。如果继承树可以找到该属性,则不调用此方法

class Foo:
def __init__(self,name):
self.name=name
def __getattr__(self, item):
print("item",item)
print("你好啊")
a=Foo("xiao")
a.age

结果:

item age
你好啊

其实这个方法是在看restfromwork中的源码中看到的

#a在APIview中这样调用的,
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) #但是在APISettings类中并没有这个DEFAULT_AUTHENTICATION_CLASSES属性
class APISettings(object): def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr) try:
# Check if present in user settings
val = self.user_settings[attr]
except KeyError:
# Fall back to defaults
val = self.defaults[attr] # Coerce import strings into classes
if attr in self.import_strings:
val = perform_import(val, attr) # Cache the result
self._cached_attrs.add(attr)
setattr(self, attr, val)
return val

应用场景:

rest_framework中的认证组件中在导入默认认证类的时候出现。

authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES

就调用了__getattr__

 def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr) try:
# Check if present in user settings
val = self.user_settings[attr]
except KeyError:
# Fall back to defaults
val = self.defaults[attr] # Coerce import strings into classes
if attr in self.import_strings:
val = perform_import(val, attr) # Cache the result
self._cached_attrs.add(attr)
setattr(self, attr, val)
return val

应用场景2:在rest_framework中的APIView中的dispatch方法中

    def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate? try:
self.initial(request, *args, **kwargs) # Get the appropriate handler method
if request.method.lower() in self.http_method_names: # 这里的request是封装后的request并不是原来的request,新的request中并没有method方法
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc:
response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
这里的request是封装后的request并不是原来的request,新的request中并没有method方法
    def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request) return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
) #这里并没有method方法

虽然request类中没有method方法,但是有__getattr__方法

    def __getattr__(self, attr):
"""
If an attribute does not exist on this instance, then we also attempt
to proxy it to the underlying HttpRequest object.
"""
try:
return getattr(self._request, attr) # self._request是老的request
except AttributeError:
return self.__getattribute__(attr)

由此可见新的request是调用的老的request中的method方法

__setattr__()

如果类自定义了__setattr__方法,当通过对实例化赋值时,就会调用__setattr__
常规的对实例属性赋值,被赋值的属性和值会存入实例属性字典__dict__中。

class ClassA(object):
def __init__(self, classname):
self.classname = classname def __setattr__(self, name, value):
# self.name = value # 如果还这样调用会出现无限递归的情况
print('invoke __setattr__') insA = ClassA('ClassA') # __init__中的self.classname调用__setattr__。
# invoke __setattr__ insA.tag = 'insA'
# invoke __setattr__

结果:

invoke __setattr__
invoke __setattr__

面向对象 反射 和item系列和内置函数和__getattr__和__setattr__的更多相关文章

  1. 绑定与非绑定方法及反射,isinstance和issubclass内置函数

    目录 绑定方法与非绑定方法 1.绑定方法 2.非绑定方法(staticmethod) isinstance和issubclass 内置函数 1.isinstance 2.issubclass 反射(面 ...

  2. python面向对象的基础语法(dir内置函数、self参数、初始化方法、内置方法和属性)

    面相对象基础语法 目标 dir 内置函数 定义简单的类(只包含方法) 方法中的 self 参数 初始化方法 内置方法和属性 01. dir 内置函数(知道) 在 Python 中 对象几乎是无所不在的 ...

  3. Python系列-python内置函数

    abs(x) 返回数字的绝对值,参数可以是整数.也可以是浮点数.如果是复数,则返回它的大小 all(iterable) 对参数中的所有元素进行迭代,如果所有的元素都是True,则返回True,函数等价 ...

  4. 【LESS系列】内置函数说明

    本文转自 http://www.cnblogs.com/zfc2201/p/3493335.html escape(@string); // 通过 URL-encoding 编码字符串 e(@stri ...

  5. SQL基础系列(2)-内置函数--转载w3school

    1.    日期函数 Mssql: SELECT GETDATE() 返回当前日期和时间 SELECT DATEPART(yyyy,OrderDate) AS OrderYear, DATEPART( ...

  6. python基础(14)-反射&类的内置函数

    反射 几个反射相关的函数可参考python基础(10)-匿名函数&内置函数中2.2.4反射相关 类的一些内置函数 __str__()&__repr__() 重写__str__()函数类 ...

  7. python语法基础-函数-内置函数和匿名函数-长期维护

    ##################     内置函数        #######################  """ 一共是 68个内置函数: 反射相关的内置函 ...

  8. day28 面向对象:反射,内置函数,类的内置方法

    面向对象进阶博客地址链接: http://www.cnblogs.com/Eva-J/articles/7351812.html 复习昨日内容: # 包 # 开发规范 # # hashlib # 登录 ...

  9. Python 面向对象 (补充) , 反射 , 内置函数

    面向对象中内置函数 issubclass方法: 检查第一个参数是否是第二个参数的子子孙孙类     返回  :   是一个布尔值 class Base(object): pass class Foo( ...

随机推荐

  1. ORA-600 [kcblin_3] 解决方法

    今日,我们一个sql在某环境执行出错,如下: ORA-00600: 内部错误代码, 参数: [kcblin_3], [103], [253952], [8192], [32769], [312], [ ...

  2. Centos 安装pureftpd工具

    之前由于vsftp上传文件会导致权限变更,因此一直不太想用ftp工具,一直sftp了,这样就导致权限过大,用户对家目录下所有文件都有权限,很容易误删其他文件.最近听同事说pure-ftp工具不错,试了 ...

  3. koa2 中 cookie 存在的中文问题

    koa2  中的 cookie 没办法直接设置中文,会报错 ‘ argument value is invalid ’ 解决办法: 先将它转成 ‘ base64 ’ 编码来存储 new Buffer( ...

  4. Mysql中 in or exists not exists not in区别 (网络整理)

    in 和or区别: 如果in和or所在列有索引或者主键的话,or和in没啥差别,执行计划和执行时间都几乎一样. 如果in和or所在列没有 索引的话,性能差别就很大了.在没有索引的情况下,随着in或者o ...

  5. HADOOP HA 踩坑 - 所有 namenode 都是standby

    报错: 无明显报错 状况: 所有namenode都是standby,即ZK服务未生效 尝试一:手动强制转化某个namenode为active 操作:在某台namenode上,执行 hdfs haadm ...

  6. 《Visual C# 从入门到精通》第二章方法和作用域——读书笔记

    第2章 方法和作用域 2.1创建方法 方法是一个基本的,强大的编程机制.可视为函数或者子程序相似的东西. 方法名是个有意义的标识符. 方法主体包含方法被调用时实际执行的语句. 声明一个方法的实例如下: ...

  7. springboot集成h2以及可视化操作

    1.新建项目

  8. R 语言 decostand() 函数

    参考自:https://wenku.baidu.com/view/ae5f76f94b35eefdc9d3336e.html

  9. fcn+caffe+siftflow实验记录

    环境搭建: vs2013,编译caffe工程,cuda8.0,cudnn5.1,python2.7. 还需要安装python的一些包.Numpy+mkl  scipy  matplotlib  sci ...

  10. js里面关于日期转换的问题

    我们拿到一个日期字符串:"2017-09-03",我们用new Date("2017-09-03")去转换成日期格式的时候,发现在火狐会报错,是因为火狐不支持这 ...