Python 创建一个";“正常”;使用所有“静态”方法从类初始化
从前,我写了一个单身班。该实现是一个仅由静态方法组成的类-我在Python 创建一个";“正常”;使用所有“静态”方法从类初始化,python,python-3.x,Python,Python 3.x,从前,我写了一个单身班。该实现是一个仅由静态方法组成的类-我在\uuuuu init\uuuuu上添加了一个异常仅用于说明,我甚至没有\uuuuuu init\uuuu,但以后需要一个: class A: x = 3 def __init__(self): raise Exception('Oh no you did not!') @staticmethod def m1(): print(A.x) @staticmethod de
\uuuuu init\uuuuu
上添加了一个异常仅用于说明,我甚至没有\uuuuuu init\uuuu
,但以后需要一个:
class A:
x = 3
def __init__(self): raise Exception('Oh no you did not!')
@staticmethod
def m1():
print(A.x)
@staticmethod
def m2(n):
A.y=8
快进几年,现在我需要创建Singleton的实例-请不要判断:)。要求:
staticmethod
装饰程序都需要删除self
参数\uuuu init\uuuu
方法class A:
x = 3 #No need to touch class variable definitions.
def __init__(self): pass #Maybe the init method will be an argument
def m1(self):
print(self.x)
def m2(self,n):
self.y = n
任何动态创建内容的解决方案(无论是否有黑客攻击)都可以。我目前正在考虑使用
inspect
来构建它,尽管我不确定它是否会成功。我不确定这是否足够,但我认为以下修改既可以用作原始单例,也可以用作普通类。有相当多的样板文件,但它是孤立于类的,而不是使用该类的代码
class A:
def __init__(self):
pass
def m1(*args):
# A.m1() means args will be empty
if args and isinstance(args[0], A):
self = args[0]
else:
self = A
print(self.x)
def m2(*args):
if isinstance(args[0], A):
self, n = args
else:
self = A
n = args[0]
self.y = n
基本上,您将对每个方法执行以下操作:
staticmethod
decorator*args
self=A
,否则设置self=args[0]
*args
的适当元素手动为每个旧参数创建局部变量A.m1()
导致打印(A.x)
,而A=A();a、 mi()
导致打印(a.x)
。同样地,A.m2(8)
是A.y=8
,而A.m2(8)
是A.y=8
我会犹豫是否尝试进一步自动化这一点;与手动更新每个方法相比,您可能会花费更多的时间来识别和尝试解决棘手的情况。我不确定这是否足够,但我认为以下修改既可以用作原始单例,也可以用作普通类。有相当多的样板文件,但它是孤立于类的,而不是使用该类的代码
class A:
def __init__(self):
pass
def m1(*args):
# A.m1() means args will be empty
if args and isinstance(args[0], A):
self = args[0]
else:
self = A
print(self.x)
def m2(*args):
if isinstance(args[0], A):
self, n = args
else:
self = A
n = args[0]
self.y = n
基本上,您将对每个方法执行以下操作:
staticmethod
decorator*args
self=A
,否则设置self=args[0]
*args
的适当元素手动为每个旧参数创建局部变量A.m1()
导致打印(A.x)
,而A=A();a、 mi()
导致打印(a.x)
。同样地,A.m2(8)
是A.y=8
,而A.m2(8)
是A.y=8
我会犹豫是否尝试进一步自动化这一点;与手动更新每个方法相比,您可能会花费更多的时间来识别和尝试解决棘手的问题。很难将所有副作用都只会影响类本身的静态单例类转换为只会影响实例对象的普通类。但也可以做相反的事情:只需使静态类拥有普通类的唯一实例并将其所有方法调用和属性访问委托给它,即可将普通类转换为单例静态类 元类可以完成这项工作。这个函数创建一个特殊属性
\u own
来保存其模型类的实例,明确地为它创建具有适当签名的方法(它还保留docstring,如果有的话),只将调用委托给\u own
,并将所有属性访问委托给\u own
import inspect
class Singletoner(type):
def __getattr__(self, attr): # delegates attribute accesses
return getattr(self._own, attr)
def __new__(cls, name, bases, namespace, **kwds):
obj = type.__new__(cls, name, bases, namespace)
X = kwds['model'] # the model class is expected with the model keyword
obj._own = X()
for name, func in inspect.getmembers(X, inspect.isfunction):
if name != '__init__':
_trans(name, func, obj) # tranfers all methods other than __init__
return obj
def _trans(name, func, clazz):
def f(*args,**kwargs):
return func(clazz._own, *args, **kwargs)
sig = inspect.signature(func) # copy signature just removing the initial param
parameters = sig.parameters
params = [t[1] for t in list(sig.parameters.items())[1:]]
f.__signature__ = sig.replace(parameters = params)
f.__doc__ = func.__doc__
setattr(clazz, name, f)
在您的示例中,非单例类将是b:
class A:
x = 3
def __init__(self): pass
def m1(self):
print(self.x)
def m2(self, n):
self.y=n
其单一委托人可声明为:
class B(metaclass=Singletoner, model=A):
pass
您可以简单地使用它:
>>> B.m1()
3
>>> B.m2(6)
>>> B.x
3
>>> B.y
6
>>> import inspect
>>> print(inspect.signature(B.m2))
(n)
>>> print(inspect.signature(B.m1))
()
很难将所有副作用只能影响类本身的静态单例类转换为只影响实例对象的普通类。但也可以做相反的事情:只需使静态类拥有普通类的唯一实例并将其所有方法调用和属性访问委托给它,即可将普通类转换为单例静态类 元类可以完成这项工作。这个函数创建一个特殊属性
\u own
来保存其模型类的实例,明确地为它创建具有适当签名的方法(它还保留docstring,如果有的话),只将调用委托给\u own
,并将所有属性访问委托给\u own
import inspect
class Singletoner(type):
def __getattr__(self, attr): # delegates attribute accesses
return getattr(self._own, attr)
def __new__(cls, name, bases, namespace, **kwds):
obj = type.__new__(cls, name, bases, namespace)
X = kwds['model'] # the model class is expected with the model keyword
obj._own = X()
for name, func in inspect.getmembers(X, inspect.isfunction):
if name != '__init__':
_trans(name, func, obj) # tranfers all methods other than __init__
return obj
def _trans(name, func, clazz):
def f(*args,**kwargs):
return func(clazz._own, *args, **kwargs)
sig = inspect.signature(func) # copy signature just removing the initial param
parameters = sig.parameters
params = [t[1] for t in list(sig.parameters.items())[1:]]
f.__signature__ = sig.replace(parameters = params)
f.__doc__ = func.__doc__
setattr(clazz, name, f)
在您的示例中,非单例类将是b:
class A:
x = 3
def __init__(self): pass
def m1(self):
print(self.x)
def m2(self, n):
self.y=n
其单一委托人可声明为:
class B(metaclass=Singletoner, model=A):
pass
您可以简单地使用它:
>>> B.m1()
3
>>> B.m2(6)
>>> B.x
3
>>> B.y
6
>>> import inspect
>>> print(inspect.signature(B.m2))
(n)
>>> print(inspect.signature(B.m1))
()
对我来说,最大的问题似乎是让方法调用
self.x
而不是A.x
这将是一个愚蠢的想法,但是你说黑客修复是可以的,所以我们可以备份