首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这是一个良好的课程建设软件工程实践吗?

这是一个良好的课程建设软件工程实践吗?
EN

Stack Overflow用户
提问于 2019-07-11 22:41:30
回答 1查看 119关注 0票数 0

这是否是一种合理和合理的方式来编写一个类,其中有一个语法糖@staticmethod,用于外部的交互?谢谢。

代码语言:javascript
复制
###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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-12 22:42:25

在回答你的问题和你的评论时,是的,写这样的代码是可能的,但我认为没有必要这样做:

代码语言:javascript
复制
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__

因此,如果实例只是计算一些东西并立即被丢弃,那么您想要的是编写一个简单的函数,而不是一个类。您不在任何地方存储状态。如果你看看它:

代码语言:javascript
复制
result = some_func(value) 

准确地看,人们在阅读时所期望的是一个函数调用。

所以不,这不是一个很好的实践,除非你想出一个很好的用例(我现在不记得了)

与此问题相关的还有了解这里__init__行为的文档。

关于你的另一个意见,我的答复如下:

在类中定义__init__以设置(已经创建的)实例的初始状态(属性值)总是发生的。但是__new__有不同的目标是定制对象创建。实例对象在运行__new__时还不存在(它是一个构造函数)。在Python中很少需要__new__,除非您需要一些东西,比如类A,它在调用A()时总是返回完全相同的对象实例( A)。普通用户定义的类通常在实例化时返回一个新对象.您可以使用id()内置函数来检查这一点。另一个用例是当您创建自己的版本(通过子类)的不可变类型。因为它是不可变的,所以已经设置了值,因此无法在__init__或更高版本中更改该值。因此,需要在此之前采取行动,在__new__中添加代码。使用__new__而不返回相同类类型的对象(这是不常见的情况),存在不运行__init__的附加问题。

如果您只是将许多方法分组在一个类中,但是在每个实例中仍然没有可以存储/管理的状态(您也注意到了这一点,因为方法主体中没有self使用),请考虑根本不使用类,并将这些方法组织成模块或包中的无私函数以供导入。因为看起来您分组只是为了组织相关的代码。

如果因为涉及状态而坚持使用类,请考虑将类分解为不超过5至7个方法的较小类。还可以考虑通过将一些小类分组到各个模块/子模块中,并使用子类来为它们提供更多的结构,因为一个很长的、简单的小类列表(或者函数)在精神上很难理解。

这与__new__的使用无关。

总之,对返回结果(或无)的函数调用或通过调用类名实例化对象使用调用的语法。在这种情况下,通常是返回预期类型的对象(被调用的类)。返回方法的结果通常涉及返回不同的类型,这在类用户看来可能是意外的。这里有一个很好的用例,一些编码器从它们的方法中返回self,以支持类似列车的语法:

代码语言:javascript
复制
 my_font = SomeFont().italic().bold()

最后,如果您不喜欢result = A().method(value),请考虑使用别名:

代码语言:javascript
复制
func = A().method
...
result = func(value)

注意代码中没有引用A()实例的情况。如果需要引用,则进一步拆分分配:

代码语言:javascript
复制
a = A()
func = a.method
...
result = func(value)

如果不需要对A()的引用,那么您可能也不需要实例,而且类只是对方法进行分组。你可以直接写

代码语言:javascript
复制
func = A.method
result = func(value)

其中无私的方法应该使用@staticmethod来修饰,因为不涉及实例。还请注意如何将静态方法转换为类之外的简单函数。

编辑:

我已经设置了一个示例,类似于您试图进行的操作。也很难判断是否有方法将结果注入下一种方法是一个多步骤的最佳选择。因为它们共享某种状态,所以它们彼此耦合,因此也可以更容易地向彼此注入错误。我假设您希望以这种方式在它们之间共享一些数据(这就是为什么要在类中设置它们):

这是一个示例类,其中一个公共方法通过调用一个内部方法链来构建结果。所有方法都依赖于对象状态(在本例中为self.offset ),尽管获得了用于计算的输入值。

正因为如此,每个方法都使用self访问状态是有意义的。您能够实例化包含不同配置的不同对象也是有意义的,因此我在这里看到@staticmethod@classmethod没有任何用处。

初始实例配置与往常一样在__init__中完成。

代码语言:javascript
复制
# 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
代码语言:javascript
复制
# 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)

产出:

代码语言:javascript
复制
37
13
22
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56998151

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档