1 什么是反射

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

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

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

四个方法的使用演示class BlackMedium:
    feature='Ugly'
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr

    def sell_house(self):
        print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
    def rent_house(self):
        print('%s 黑中介租房子啦,傻逼才租呢' %self.name)

b1=BlackMedium('万成置地','回龙观天露园')

#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))

#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()

# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))

#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))

#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错

print(b1.__dict__)

#类也是对象

class Foo(object):

    staticField = "old boy"

    def __init__(self):
        self.name = 'wupeiqi'

    def func(self):
        return 'func'

    @staticmethod
    def bar():
        return 'bar'

print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')print getattr(Foo,'bar')()#注意有什么不同
#反射当前 模块成员import sys
def s1():
    print 's1'

def s2():
    print 's2'
this_module = sys.modules[__name__]
hasattr(this_module, 's1')
getattr(this_module, 's2')
new_method_s2=getattr(this_module,'s2')#相当于给函数起了个别名new_method_s2()s2()#输出结果相同

导入其他模块,利用反射查找该模块是否存在某个方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def test():
    print('from the test')

#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
程序目录:
module_test.py
index.py

当前文件:
index.py
"""

import module_test as obj

#obj.test()

print(hasattr(obj,'test'))

getattr(obj,'test')()

反射的好处:  1.实现可插播机制  2.动态导入模块#--------------------------------

__setattr__,__delattr__,__getattr__

class Foo:    x = 1

    def __init__(self, y):        self.y = y

    def __getattr__(self, item):        print('----> from getattr:你找的属性不存在')

    def __setattr__(self, key, value):        print('----> from setattr')        # self.key=value #这就无限递归了,你好好想想        # self.__dict__[key]=value #应该使用它

    def __delattr__(self, item):        print('----> from delattr')        # del self.item #无限递归了        self.__dict__.pop(item)

# __setattr__添加/修改属性会触发它的执行f1 = Foo(10)print(f1.__dict__)  # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值f1.z = 3print(f1.__dict__)

# __delattr__删除属性的时候会触发f1.__dict__['a'] = 3  # 我们可以直接修改属性字典,来完成添加/修改属性的操作del f1.aprint(f1.__dict__)

# __getattr__只有在使用点调用属性且属性不存在的时候才会触发f1.xxxxxx

class List(list):  # 继承list所有的属性,也可以派生出自己新的,比如append和mid    def append(self, p_object):        ' 派生自己的append:加上类型检查'        if not isinstance(p_object, int):            raise TypeError('must be int')        super().append(p_object)

    @property    def mid(self):        '新增自己的属性'        index = len(self) // 2        return self[index]

l = List([1, 2, 3, 4])print(l)l.append(5)print(l)# l.append('1111111') #报错,必须为int类型

print(l.mid)

# 其余的方法都继承list的l.insert(0, -123)print(l)l.clear()print(l)

class List(list):    def __init__(self, item, tag=False):        super().__init__(item)        self.tag = tag

    def append(self, p_object):        if not isinstance(p_object, str):            raise TypeError        super().append(p_object)

    def clear(self):        if not self.tag:            raise PermissionError        super().clear()

l = List([1, 2, 3], False)print(l)print(l.tag)

l.append('saf')print(l)

# l.clear() #异常

l.tag = Truel.clear()

# 练习(clear加权限限制)



python 面向对象编程 之 反射的更多相关文章

  1. python面向对象编程进阶

    python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...

  2. python 面向对象编程学习

    1. 问题:将所有代码放入一个py文件:无法维护 方案:如果将代码才分放到多个py文件,好处: 1. 同一个名字的变量互相不影响 2.易于维护 3.引用模块: import module 2.包:解决 ...

  3. python 面向对象编程(一)

    一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class c ...

  4. Python面向对象编程指南

    Python面向对象编程指南(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1SbD4gum4yGcUruH9icTPCQ 提取码:fzk5 复制这段内容后打开百度网 ...

  5. Python面向对象编程(下)

    本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...

  6. Python 面向对象编程——访问限制

    <无访问限制的对象> 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑.但是,从前面Student类的定义来看(见:Py ...

  7. Python 面向对象编程 继承 和多态

    Python 面向对象编程 继承 和多态 一:多继承性 对于java我们熟悉的是一个类只能继承一个父类:但是对于C++ 一个子类可以有多个父亲,同样对于 Python一个类也可以有多个父亲 格式: c ...

  8. Python 面向对象编程基础

    Python 面向对象编程基础 虽然Pthon是解释性语言,但是Pthon可以进行面向对象开发,小到 脚本程序,大到3D游戏,Python都可以做到. 一类: 语法: class 类名: 类属性,方法 ...

  9. python面向对象编程学习

    python面向对象编程 基本概念理解 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...

随机推荐

  1. cap文件的格式说明

    前面24个字节是.cap文件的文件头. 头信息对应的结构体为:struct pcap_file_header {  bpf_u_int32 magic;  u_short version_major; ...

  2. Idea使用Maven异常 --- Maven网络代理设置

    在conf/setting.xml和m2/repository/setting.xml中加入: <proxies> <!-- proxy | Specification for on ...

  3. ArcGIS案例学习笔记2_2_txtexcel空间可视化和空间插值

    ArcGIS案例学习笔记2_2_txt/excel空间可视化和空间插值 计划时间:第二天下午 教程:pdf page=337 数据:chapter8/ex4 方法: 1.加载xy.txt和gdp.tx ...

  4. python 如何注释

    一.单行注释     单行注释以#开头,例如:    print 6 #输出6 二.多行注释     (Python的注释只有针对于单行的注释(用#),这是一种变通的方法)     多行注释用三引号' ...

  5. Android Debug Bridge命令介绍[转]

    Android Debug Bridge命令介绍 Android Debug Bridge的一些基本命令.这个工具直译过来就是Android调试桥的意思.它提供了强大的特性,例如复制文件到设备或从设备 ...

  6. ceph部署手册

    CentOS7.2部署Luminous版Ceph-12.2.0 在CentOS7.2上安装部署Luminous版Ceph-12.2.0.由于ceph的Luminous版本默认使用bluestore作为 ...

  7. python进行爬虫

    使用python进行网络爬虫 非结构画数据 转为 结构化数据.需要借助ETL(数据抽取,转换,存储)进行. 非结构化数据蕴含着丰富的价值.需要借助ETL进行转换成结构化数据,才能变成有价值的数据.比如 ...

  8. Matlab练习——rpy2tr函数与自己实现的ZYX欧拉角的结果不同的问题

    问题背景:在根据<机器人导论>这本书的Z-Y-X欧拉角原理用Matlab实现旋转矩阵求解时,发现与直接调用机器人工具箱中的rpy2tr()函数得出的结果并不相同. 首先:先检查自己写的函数 ...

  9. JAVA第五周 动手动脑

    public class Example { int x = 3;//类的实例变量,初始化值为3 static int y = 4;//类的静态变量,初始化值为4 public static void ...

  10. mui-当使用addeleventlisener()方法绑定事件时选择器无法绑定事件

    在mui中绑定事件不能用jQuery或mui(“#XX”)的形式选取某个元素,而是document.getelementbyid()的形式 mui(“#XX”)可以使用on方法绑定事件