类方法:在函数中使用函数

时间:2018-08-23 14:43:57

标签: python

我遇到一种情况,我正在使用@classmethod为类创建构造函数。在此构造函数中,将调用一个函数,然后依次调用另一个函数。但这要么不起作用,要么(可能是)我正在做一些使其不起作用的事情。这是一个缩影示例:

class testclass:
    def __init__(self, x):
        self.x = x

    @classmethod
    def constructor(cls, x):
        adj_x = cls.outer_adjust(cls, x)
        return testclass(adj_x)

    def outer_adjust(self, x):
        return self.inner_adjust(x)

    def inner_adjust(self, x):
        return x + 1

test_instance = testclass.constructor(4)

这会产生一条错误消息:

inner_adjust() missing 1 required positional argument: 'x'

我可以通过将自身显式传递给inner_adjust来使其正常工作,例如

def outer_adjust(self, x):
    return self.inner_adjust(self, x)

但这意味着outer_adjust之外不能使用constructor方法,这不是我想要的。

非常感谢收到任何帮助。

这是一个更详细的示例,其中显示了两个构造函数。我正在尝试遵循中描述的构造方法 What is a clean, pythonic way to have multiple constructors in Python? 从本质上讲,这是构造函数进行一些处理,以确定在实例化类时应将哪些变量传递给 init 。 两个构造函数都给出相同的错误:

if_char_is_z_make_it_a() missing 1 required positional argument: 'char_input'

和以前一样,我需要能够在构造函数之外(即,正常使用类时)使用if_char_is_make_it_a函数。

class testclass:
    def __init__(self, char):
        self.char = char

    @classmethod
    def constructor_from_int(cls, int_input):
        as_char = chr(int_input)
        char = cls.process_char(cls, as_char)
        return testclass(char)

    @classmethod
    def constructor_from_char(cls, char_input):
        char = cls.process_char(cls, char_input)
        return testclass(char)

    def process_char(self, char_input):
        processed_char = '(' + char_input + ')'
        output_char = self.if_char_is_z_make_it_a(processed_char)
        return output_char

    def if_char_is_z_make_it_a(self, char_input):
        if char_input == '(z)':
            return '(a)'
        return char_input

test_instance = testclass.constructor_from_char('a')

3 个答案:

答案 0 :(得分:2)

cls.outer_adjust调用constructor时,您正在调用未绑定的outer_adjust方法。

因此,您将类本身作为self而不是实例传递给希望接收实例作为参数的方法。

尽管,没有真正理由使用constructor方法。这正是__init__的目的。

class testclass:
    def __init__(self, x):
        self.x = self.outer_adjust(x)

    def outer_adjust(self, x):
        return self.inner_adjust(x)

    def inner_adjust(self, x):
        return x + 1

test_instance = testclass(4)

如果您确实需要在实例化之前 上完成x上的转换,请改用__new__。虽然,这通常不是必需的。

多个构造函数

如果由于某种原因您仍然需要一个constructor方法,例如,如果您想要多个构造函数。然后请记住outer_adjustinner_adjust是实例方法,这意味着在创建实例之后,必须将它们称为

class testclass:
    def __init__(self, x):
        self.x = x

    @classmethod
    def constructor1(cls, x):
        instance = cls(x)
        instance.outer_adjust()
        return instance

    @classmethod
    def constructor2(cls, x):
        instance = cls(x)
        instance.inner_adjust()
        return instance

    def outer_adjust(self):
        print('Do something else')
        return self.inner_adjust()

    def inner_adjust(self):
        self.x += 1

请注意,我不需要在构造函数方法中调用testclass,而只需调用cls。由于这是一个类方法,因此我们无需显式命名该类。这样会更好,特别是如果您要使用继承。

答案 1 :(得分:1)

基本上,您在这里所做的工作应通过用作构造函数的__new__完成。

class testclass:
    def __init__(self, x):
        self.x = x

    def __new__(cls, *args, **kwargs):
        instance = super(testclass, cls).__new__(cls, *args, **kwargs)
        instance.outer_adjust(args[0])
        return instance

    def outer_adjust(self, x):
        return self.inner_adjust(x)

    def inner_adjust(self, x):
        self.x = x + 1

test_instance = testclass(4)

答案 2 :(得分:0)

您正在滥用self。类方法的重点是使用cls参数作为构造函数,而不是用testclass(adj_x)显式命名该类。另外,在cls.outer_adjust(cls, x)调用期间,您正在传递类而不是实例,因为您没有使用任何实例属性,所以会发生

关于您的问题,无法避免使用x参数。 inner_adjust通过1增加一些值,因此您必须给它一些增加的值。这个想法是要

def constructor(cls, x):
    return cls(x)

def inner_adjust(self):
    return self.x += 1

然后做类似的事情

object= testclass.constructor(12)
object.inner_adjust()