这是写一个类的方法,听起来很合理吗?该类中有一个语法糖@static方法,用于与外界交互?谢谢。
###scrip1.py###
import SampleClass.method1 as method1
output = method1(input_var)
###script2.py###
class SampleClass(object):
def __init__(self):
self.var1 = 'var1'
self.var2 = 'var2'
@staticmethod
def method1(input_var):
# Syntactic Sugar method that outside uses
sample_class = SampleClass()
result = sample_class._method2(input_var)
return result
def _method2(self, input_var):
# Main method executes the various steps.
self.var4 = self._method3(input_var)
return self._method4(self.var4)
def _method3(self):
pass
def _method4(self):
pass
答案 0 :(得分:2)
回答您的问题和评论,是的,可以编写这样的代码,但我认为这样做没有意义:
class A:
def __new__(cls, value):
return cls.meth1(value)
def meth1(value):
return value + 1
result = A(100)
print(result)
# output:
101
您不能存储对类A实例的引用,因为您获得方法结果而不是A实例。因此,将不会调用现有的__init__
。
因此,如果实例只是计算某些内容并立即将其丢弃,那么您想要的是编写一个简单的函数,而不是一个类。您不在任何地方存储状态。 如果你看的话:
result = some_func(value)
完全符合人们在阅读时所期望的功能调用。
因此,除非您为此提出了一个很好的用例(我现在不记得了),否则这不是一个好习惯。
与此问题相关的还有文档here,以了解__new__
和__init__
的行为。
关于我的回答下方的其他评论:
始终在类中定义__init__
来设置(已经)创建的实例的初始状态(属性值)。但是__new__
具有自定义对象创建的不同目标。运行__new__
时,实例对象尚不存在(它是一个构造函数)。除非您需要类似 singleton 之类的东西,否则在Python中很少需要__new__
,比如说A
类,当用{{进行调用时,它总是返回与A相同的对象实例。 1}}。普通的用户定义类通常在实例化时返回一个新对象。您可以使用A()
内置函数进行检查。另一个用例是当您创建自己的不可变类型的版本(通过子类化)时。因为它是不可变的,所以已经设置了该值,无法在id()
或更高版本中更改该值。因此,需要在此之前采取行动,在__init__
中添加代码。使用__new__
而不返回相同类类型的对象(这是不常见的情况)会导致无法运行__new__
的问题。
如果您只是在一个类中对许多方法进行分组,但是在每个实例中仍然没有要存储/管理的状态(您也注意到方法主体中缺少__init__
的使用),请考虑不要现在完全使用一个类并组织这些方法,现在在导入的模块或包中已变成无私的函数。因为看起来您正在分组只是为了组织相关代码。
如果因为涉及状态而坚持使用类,请考虑使用不超过5到7个方法将类拆分为较小的类。还可以考虑通过将各个小类分类为各个模块/子模块并使用子类来为它们提供更多的结构,因为一长串简单的小类(无论如何还是函数)在精神上很难遵循。
这与self
的使用无关。
总而言之,对返回结果(或无)的函数调用或通过调用类名的对象实例化使用调用的语法。在这种情况下,通常是返回预期类型的对象(称为类)。返回方法的结果通常涉及返回不同的类型,这对于类用户而言似乎是意外的。有一个非常接近的用例,其中一些编码器从其方法中返回__new__
以允许使用类似火车的语法:
self
最后,如果您不喜欢 my_font = SomeFont().italic().bold()
,请考虑一个别名:
result = A().method(value)
请注意如何在代码中不引用A()实例。 如果您需要参考拆分,请进一步分配:
func = A().method
...
result = func(value)
如果不需要引用A(),那么您可能也不需要实例,并且该类只是将方法分组。你可以写
a = A()
func = a.method
...
result = func(value)
其中无私方法应使用func = A.method
result = func(value)
装饰,因为其中不涉及实例。还请注意如何将静态方法转换为类之外的简单函数。
我已经建立了一个与您尝试完成的示例类似的示例。对于多步骤过程,也很难判断是否有将结果注入下一方法的方法是最佳选择。因为它们共享某种状态,所以它们彼此耦合,因此也可以更轻松地向彼此注入错误。我假设您想以这种方式在它们之间共享一些数据(这就是为什么要在一个类中设置它们):
因此,这是一个示例类,其中的公共方法通过调用内部方法链来构建结果。所有方法都依赖于对象状态,在这种情况下,尽管获得了用于计算的输入值,但是在这种情况下,@staticmethod
仍然如此。
因此,每个方法都使用self来访问状态是有意义的。能够实例化具有不同配置的不同对象也很有意义,因此我在这里看不到self.offset
或@staticmethod
的用处。
与往常一样,初始实例配置是在@classmethod
中完成的。
__init__
# file: multistepinc.py
def __init__(self, offset):
self.offset = offset
def result(self, value):
return self._step1(value)
def _step1(self, x):
x = self._step2(x)
return self.offset + 1 + x
def _step2(self, x):
x = self._step3(x)
return self.offset + 2 + x
def _step3(self, x):
return self.offset + 3 + x
def get_multi_step_inc(offset):
return MultiStepInc(offset).result
输出:
# file: multistepinc_example.py
from multistepinc import get_multi_step_inc
# get the result method of a configured
# MultiStepInc instance
# with offset = 10.
# Much like an object factory, but you
# mentioned to prefer to have the result
# method of the instance
# instead of the instance itself.
inc10 = get_multi_step_inc(10)
# invoke the inc10 method
result = inc10(1)
print(result)
# creating another instance with offset=2
inc2 = get_multi_step_inc(2)
result = inc2(1)
print(result)
# if you need to manipulate the object
# instance
# you have to (on file top)
from multistepinc import MultiStepInc
# and then
inc_obj = MultiStepInc(5)
# ...
# ... do something with your obj, then
result = inc_obj.result(1)
print(result)