python装饰器实现的函数重写_python-将装饰器附加到类中的所有函数

当然,当您想修改python创建对象的方式时,元类是最pythonic的方式。 可以通过重写您的类的a = 10方法来完成。 但是我想提一下围绕这个问题(特别是针对python 3.x)的一些观点:

a = 10不能保护特殊方法,因为它们是函数类型。 作为更通用的方法,您可以修饰名称不以双下划线开头的对象(print(myinstance.a))。 此方法的另一个好处是,它还覆盖了存在于名称空间中并以__new__开头但不像__new__、__init__等起作用的那些对象。

print(myinstance.a)标题中的a = 10自变量在__new__中不包含类属性。原因是__new__在__init__(初始化)之前执行。

不需要使用a = 10作为装饰器,因为在大多数情况下,您是从另一个模块导入装饰器的。

如果您的班级包含一个全局项目(在a = 10的外侧),用于拒绝装饰,同时检查名称是否不是以print(myinstance.a)开头,则可以使用__new__检查类型,以确保您未在装饰非功能性物品 目的。

这是您可以使用的示例metacals:

class TheMeta(type):

def __new__(cls, name, bases, namespace, **kwds):

# if your decorator is a class method of the metaclass use

# `my_decorator = cls.my_decorator` in order to invoke the decorator.

namespace = {k: v if k.startswith('__') else my_decorator(v) for k, v in namespace.items()}

return type.__new__(cls, name, bases, namespace)

演示:

def my_decorator(func):

def wrapper(self, arg):

# You can also use *args instead of (self, arg) and pass the *args

# to the function in following call.

return "the value {} gets modified!!".format(func(self, arg))

return wrapper

class TheMeta(type):

def __new__(cls, name, bases, namespace, **kwds):

# my_decorator = cls.my_decorator (if the decorator is a classmethod)

namespace = {k: v if k.startswith('__') else my_decorator(v) for k, v in namespace.items()}

return type.__new__(cls, name, bases, namespace)

class MyClass(metaclass=TheMeta):

# a = 10

def __init__(self, *args, **kwargs):

self.item = args[0]

self.value = kwargs['value']

def __getattr__(self, attr):

return "This class hasn't provide the attribute {}.".format(attr)

def myfunction_1(self, arg):

return arg ** 2

def myfunction_2(self, arg):

return arg ** 3

myinstance = MyClass(1, 2, value=100)

print(myinstance.myfunction_1(5))

print(myinstance.myfunction_2(2))

print(myinstance.item)

print(myinstance.p)

输出:

the value 25 gets modified!!

the value 8 gets modified!!

1

This class hasn't provide the attribute p. # special method is not decorated.

要检查上述注释中的第三项,您可以取消注释行a = 10并注释print(myinstance.a),然后查看结果,然后按以下所示更改__new__中的字典理解,然后再次查看结果:

namespace = {k: v if k.startswith('__') and not isinstance(v, types.FunctionType)\

else my_decorator(v) for k, v in namespace.items()}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值