我可以定义一个可以直接在类实例上调用的静态方法吗?例如。,

MyClass.the_static_method()

当前回答

也许最简单的选择就是将这些函数放在类之外:

class Dog(object):
    def __init__(self, name):
        self.name = name

    def bark(self):
        if self.name == "Doggy":
            return barking_sound()
        else:
            return "yip yip"

def barking_sound():
    return "woof woof"

使用此方法,可以将修改或使用内部对象状态(具有副作用)的函数保留在类中,并且可以将可重用的实用程序函数移到外部。

假设这个文件名为dogs.py。要使用这些文件,您可以调用dogs.barking_sound()而不是dogs.Dog.barking_sound。

如果确实需要静态方法作为类的一部分,可以使用staticmethoddecorator。

其他回答

总结其他人的回答并补充,在python中声明静态方法或变量有很多种方法。

使用staticmethod()作为装饰符:可以简单地在声明的方法(函数)上方放置一个修饰符,使其成为静态方法。例如。

class Calculator:
    @staticmethod
    def multiply(n1, n2, *args):
        Res = 1
        for num in args: Res *= num
        return n1 * n2 * Res

print(Calculator.multiply(1, 2, 3, 4))              # 24

使用staticmethod()作为参数函数:此方法可以接收函数类型的参数,并返回传递函数的静态版本。例如。

class Calculator:
    def add(n1, n2, *args):
        return n1 + n2 + sum(args)

Calculator.add = staticmethod(Calculator.add)
print(Calculator.add(1, 2, 3, 4))                   # 10

使用classmethod()作为装饰符:@classmethod对函数的影响与@staticmethod类似,但是这一次,需要在函数中接受一个额外的参数(类似于实例变量的self参数)。例如。

class Calculator:
    num = 0
    def __init__(self, digits) -> None:
        Calculator.num = int(''.join(digits))

    @classmethod
    def get_digits(cls, num):
        digits = list(str(num))
        calc = cls(digits)
        return calc.num

print(Calculator.get_digits(314159))                # 314159

使用classmethod()作为参数函数:@classmethod也可以用作参数函数,以防不想修改类定义。例如。

class Calculator:
    def divide(cls, n1, n2, *args):
        Res = 1
        for num in args: Res *= num
        return n1 / n2 / Res

Calculator.divide = classmethod(Calculator.divide)

print(Calculator.divide(15, 3, 5))                  # 1.0

直接申报在所有其他方法外部但在类内部声明的方法/变量自动是静态的。

class Calculator:   
    def subtract(n1, n2, *args):
        return n1 - n2 - sum(args)

print(Calculator.subtract(10, 2, 3, 4))             # 1

整个计划

class Calculator:
    num = 0
    def __init__(self, digits) -> None:
        Calculator.num = int(''.join(digits))
    
    
    @staticmethod
    def multiply(n1, n2, *args):
        Res = 1
        for num in args: Res *= num
        return n1 * n2 * Res


    def add(n1, n2, *args):
        return n1 + n2 + sum(args)
    

    @classmethod
    def get_digits(cls, num):
        digits = list(str(num))
        calc = cls(digits)
        return calc.num


    def divide(cls, n1, n2, *args):
        Res = 1
        for num in args: Res *= num
        return n1 / n2 / Res


    def subtract(n1, n2, *args):
        return n1 - n2 - sum(args)
    



Calculator.add = staticmethod(Calculator.add)
Calculator.divide = classmethod(Calculator.divide)

print(Calculator.multiply(1, 2, 3, 4))              # 24
print(Calculator.add(1, 2, 3, 4))                   # 10
print(Calculator.get_digits(314159))                # 314159
print(Calculator.divide(15, 3, 5))                  # 1.0
print(Calculator.subtract(10, 2, 3, 4))             # 1

有关掌握Python中的OOP,请参阅Python文档。

您实际上不需要使用@staticmethoddecorator。只需声明一个方法(不需要self参数)并从类中调用它。装饰器仅在您希望能够从实例调用它时才存在(这不是您想要做的)

大多数情况下,你只是使用函数。。。

我认为史蒂文实际上是对的。为了回答最初的问题,那么,为了设置一个类方法,只需假设第一个参数不是一个调用实例,然后确保只从类调用该方法。

(注意,这个答案指的是Python 3.x。在Python 2.x中,调用类本身的方法会得到一个TypeError。)

例如:

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    def rollCall(n): #this is implicitly a class method (see comments below)
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))

fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)

在这段代码中,“rollCall”方法假设第一个参数不是实例(如果它是由实例而不是类调用的话)。只要从类而不是实例调用“rollCall”,代码就会正常工作。如果我们尝试从实例调用“rollCall”,例如:

rex.rollCall(-1)

然而,它将导致引发异常,因为它将发送两个参数:自身和-1,而“rollCall”仅定义为接受一个参数。

顺便说一句,rex.rollCall()将发送正确数量的参数,但也会引发异常,因为现在n将表示Dog实例(即rex),而函数期望n是数字。

这就是装饰的由来:如果我们在“rollCall”方法前面加上

@staticmethod

然后,通过显式声明该方法是静态的,我们甚至可以从实例调用它。现在

rex.rollCall(-1)

会起作用。然后,在方法定义之前插入@staticmethod会阻止实例将自身作为参数发送。

您可以通过使用或不使用注释掉的@staticmethod行尝试以下代码来验证这一点。

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    @staticmethod
    def rollCall(n):
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))


fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)

Python静态方法可以通过两种方式创建。

使用静态方法()类算术:def-add(x,y):返回x+y#创建添加静态方法Arithmetic.add=静态方法(算术.add)print('结果:',算术.add(15,10))

输出:

结果:25

使用@staticmethod类算术:#创建添加静态方法@静态方法def-add(x,y):返回x+yprint('结果:',算术.add(15,10))

输出:

结果:25

Python中的静态方法?是否可以在Python中使用静态方法,以便我可以调用它们而不初始化类,例如:ClassName.StaticMethod()

是的,静态方法可以这样创建(虽然使用下划线而不是CamelCase来创建方法有点像Python):

class ClassName(object):

    @staticmethod
    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

上面使用了decorator语法。此语法等效于

class ClassName(object):

    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

    static_method = staticmethod(static_method)

这可以按照您所描述的方式使用:

ClassName.static_method()

静态方法的一个内置示例是Python 3中的str.maketrans(),它是Python 2中字符串模块中的一个函数。


正如您所描述的,另一个可以使用的选项是classmethod,不同之处在于classmethod将类作为隐式第一个参数,如果是子类,则将子类作为隐的第一个参数。

class ClassName(object):

    @classmethod
    def class_method(cls, kwarg1=None):
        '''return a value that is a function of the class and kwarg1'''

请注意,cls不是第一个参数的必需名称,但如果您使用其他名称,大多数有经验的Python程序员会认为它做得很糟糕。

这些通常用作替代构造函数。

new_instance = ClassName.class_method()

内置示例是dict.fromkeys():

new_dict = dict.fromkeys(['key1', 'key2'])