python 类方法的动态调用
2017-04-17
原创作品:首发u3v3, 转载请保留
地址:https://www.u3v3.com/ar/1313
作者ID:Yi_Zhi_Yu
首发日期:2017.4.17
Python学习群:278529278 (欢迎交流)
PHP中的动态调用
PHP 中对对象方法
可以方便的使用, 如下
<?php
class T
{
public function a(){
var_dump('Hello A');
}
}
$t = new T();
$t->a();
$func = 'a';
$t->{$func}(); //这里就是动态调用 和 $t->a()调用一样
上面的例子可以看出, 通过动态调用, 我们可以以对象->函数名字符串()
的方式动态的调用类对象
python 中的动态调用
PHP 中的动态调用如此简单, 那Python中呢
python 中没有像PHP 那样的通过字符串作为函数名调用的方式
, 但python 有另外一种实现方式
我们知道, 在python的类中, 有这么一个特殊的函数 __getattr__
当我们通过obj.attr_name
的方式获取obj
中不存在的属性时, 就会触发该函数
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Tony Wang @ 2017-04-18 00:31:12
class T():
name = 'Yi_Zhi_Yu'
def __getattr__(self, attr_name):
return 'You are try get attr: {}'.format(attr_name)
if __name__ == '__main__':
t = T()
print(t.name) # Yi_Zhi_Yu
print(t.age) # You are try get attr: age
那这和动态调用有什么关系呢,
在python 中, 类里面的的函数其实也是类的属性
, 只不过类型比较特殊
理解了这一点, 我们看下面
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Tony Wang @ 2017-04-18 00:31:12
class T():
name = 'Yi_Zhi_Yu'
"""
def __getattr__(self, attr_name):
return 'You are try get attr: {}'.format(attr_name)
"""
def __getattr__(self, func_name):
return 'You are try get method: {}'.format(func_name)
if __name__ == '__main__':
t = T()
print(t.get_age) # You are try get method: get_age
现在我们已经能将get_age
动态的传递到类的对象中了, 下面就是调用函数了
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Tony Wang @ 2017-04-18 00:31:12
class T():
name = 'Yi_Zhi_Yu'
"""
def __getattr__(self, attr_name):
return 'You are try get attr: {}'.format(attr_name)
"""
def __getattr__(self, func_name):
def func():
return 'You have call method: {}'.format(func_name)
#return 'You are try get method: {}'.format(func_name)
return func
if __name__ == '__main__':
t = T()
print(t.get_age()) # You have call method: get_age
print(t.get_sex()) # You have call method: get_sex
现在我们就实现了函数的动态调用,
如果需要参数呢
其实就是定义的func
函数里, 加上参数即可
def __getattr__(self, func_name):
def func(*args, **kwargs): # 这里的定义带了参数
return 'You have call method: {}'.format(func_name)
#return 'You are try get method: {}'.format(func_name)
return func
应用场景
在python 中, 动态调用的实际的应用场景是什么
这里我举例说明一个
我们使用对redis
进行操作的时候, 有时候需要添加一个代理类, 如下
class RedisClient():
def init_con(self, *args, **args):
# do init things
# like connect redis
pass
然后希望直接通过这个 RedisClient
进行redis操作, 比如 set, get, hget...
,
redis_client.set(....)
redis_client.get(....)
....
这样调用的话, 就需要将pyredis
中的所有函数都在RedisClient 中写一遍, 那就有点得不偿失了
这里实际就是希望能够做到动态调用, 将RedisClient
中的操作, 根据操作名, 直接映射到实际的pyredis
操作
所以, 我们在RedisClient 中
class RedisClient():
....
def __getattr__(self, func_name):
def func(*args, **args):
# 这里的 getattr 实际就相当于redis_con.<func_name>了
return getattr(self.redis_conn, func_name)(*args, **args)
if __name__ == '__main__':
redis_client = RedisClient()
redis_client.init_con(.....)
redis_client.set('key_name', 'key_value')
就实现了代理动态调动pyredis
的操作的目的了