Python 基础 四

今天我们先介绍一下反射这个概念,啥是反射?反射就是自己检测自己。在我们Python的面向对象中的反射是啥意思呢?就是过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

在Python中四个产生反射的函数,分别是:hasattr();getattr();setattr();delattr();

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

hasattr((object, name, default=None))
判断object中有没有一个name字符串对应的方法或属性
def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value

    Get a named attribute from an object; getattr(x, ‘y‘) is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn‘t
    exist; without it, an exception is raised in that case.
    """
    pass

getattr(object, name, default=None)
def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.

    setattr(x, ‘y‘, v) is equivalent to ``x.y = v‘‘
    """
    pass

setattr(x, y, v)
def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.

    delattr(x, ‘y‘) is equivalent to ``del x.y‘‘
    """
    pass

delattr(x, y)

四种方法的演示:

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__)

四个方法的使用演示

为啥要使用反射机制呢?
好处一:实现可插拔机制(就是你与一个人一起开发一个项目若一个人暂时有时不能做他自己负责的项目但你要使用调用他的某些功能,so ,你就可以使用这个反射拉)

总之反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能

好处二:动态导入模块(基于反射当前模块成员)

# from m1 import t
# t.test1()

module_t = __import__(‘m1.t‘) # 实质只是导入了最顶层的那个模块m1

print(module_t) # <module ‘m1‘ from ‘C:\\Users\\lenovo\\Desktop\\Py_fullstack_s4\\pythonday15\\m1\\__init__.py‘>

# module_t.test1() #AttributeError: module ‘m1‘ has no attribute ‘test1‘
# module_t.t.test1()

import importlib

m = importlib.import_module(‘m1.t‘) # <module ‘m1.t‘ from ‘C:\\Users\\lenovo\\Desktop\\Py_fullstack_s4\\pythonday15\\m1\\t.py‘>
print(m)
m.test1()
m._test2() #只有 import * 的时候才是导入会报错误

二、__setattr__;__getattr__;__delattr__;的使用

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=3
print(f1.__dict__)

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

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

三种方法的使用

时间: 2024-10-06 00:43:18

Python 基础 四的相关文章

Python基础(四) 基础拾遗、数据类型进阶

一.基础拾遗 (一).变量作用域 外层变量,可以被内层变量直接调用:内层变量,无法被外层变量使用.这种说法在其它语言中适用,在python中除了栈以外,正常的变量作用域,只要执行声明并在内存中存在,该变量就可以在下面的代码中使用. (二).位运算符.三元运算 1,位运算符,请看下面代码 1 128 64 32 16 8 4 2 1 2 0 0 0 0 0 0 0 0 3 4 5 #!/usr/bin/env python 6 7 a=60 #00111100 (将十进制转换成二进制,进行位运算)

python基础四

递归调用.高阶函数.函数作用域.python内置函数.装饰器.模块.random.json串和积累 一.递归调用 递归调用就是一个函数自己调用自己,自我调用最多调用999次. 特性:1.必须有一个明确的结束条件: 2.每次进入更深一层递归时,问题规模相比上次递归都应该有所减少: 3.递归效率不高,建议少用递归 def test(): n=int(input('please input a number: ')) if n%2==0: return True print('输入的不是偶数') te

python基础四(模块的导入)

一.导入模块?从模块导入时,一般使用 import sys(用sys模块举例) #这种方式导入模块,要使用这个模块其中的功能,语法为模块名称**.**功能,如print(sys.path) from sys import path #这种方式导入模块要使用模块中的功能,直接功能名即可print(sys),如果要导入该模块多个功能可以以逗号隔开 from SomeMode import * #这种方式和第二种一样只是把具体的功能名换成了*(导入所有),这种方式也有弊端,假如你导入的模块都有一个名为

[python基础(四)]条件和条件语句

1.print和import1.1 print 略1.2 import(1)impore somemodule (2)from somemodule import somefunction(3)from somemodule import somefunction,anotherfunction(4)from somemodule import*(5)import somemodule as somename #为整个模块提供别名(6)from somemodule import somefun

python基础(四)运算

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Python的运算符和其他语言类似 (我们暂时只了解这些运算符的基本用法,方便我们展开后面的内容,高级应用暂时不介绍) 数学运算 >>>print 1+9        # 加法 >>>print 1.3-4      # 减法 >>>print 3*5        # 乘法 >>>print 4.5/1.5   

Python基础 ( 四 )

#函数 #函数的定义 def sum1(x,y) : --> 也可不传参数或传入多个参数 'this function is used in caculation' --> 注释,可以说明此函数的信息 x = x + y return x --> 若没有返回值则(返回None)成为过程(此说明python中没意义,别的程序语言可能就有用) return 1,2,['adsf',11] 这样返回的是一个元组(1,2,['adsf',11]) #形参和实参    形参 : def sum1(

Python基础四--random,so ,sys模块

一.random 1. 产生随机小数(0,1):random.random(): 2. 产生[1,5]范围内的整数:random.randint(1,5): 3. 产生[1,5)范围内的整数:random.randrange(1,5); 4. 列表元素任意1个元素:random.choice([1,'ab',[2,3]]); 5. 列表元素任意2个组合(list):random.sample([1,'ab',[2,3]],2); 6. (1,5)之间的小数:random.uniform(1,5)

python基础(四)字符串处理

字符串处理 msg = 'my name is sylar' capitalize方法,将字符串的首字母大写 print 'capitalize方法:', msg.capitalize() swapcase方法用于对字符串的大小写字母进行转换.upper print 'swapcase方法:', msg.swapcase() print 'upper方法:',msg.upper() msq_lower = msg.upper() print 'lower方法:',msq_lower, msq_l

python基础四:装饰器

装饰器本质:就是函数,功能是为其他函数添加附加功能 装饰器原则: 不修改被修饰函数的源代码 不修改修饰函数的调用方式 装饰器的知识储备: 装饰器 = 高阶函数 + 函数嵌套 + 闭包 初识装饰器 先看一个需求:下面这个函数用来计算1到20的和 def calc(l): res = 0 for i in l: time.sleep(0.01) res += i return res result = calc(range(1,21)) print(result) 但现在需求有变,不仅要计算1到20