简体   繁体   English

使用静态方法有什么好处?

[英]What is the advantage of using static methods?

I ran into unbound method error in python with the code我在 python 中遇到了未绑定的方法错误,代码如下

import random

class Sample(object):
    '''This class defines various methods related to the sample'''

    def drawSample(samplesize,List):
        sample=random.sample(List,samplesize)
        return sample

Choices=range(100)
print Sample.drawSample(5,Choices)

After reading many helpful posts here, I figured how I could add @staticmethod above to get the code working.在这里阅读了许多有用的帖子后,我想出了如何在上面添加@staticmethod以使代码正常工作。 I am a python newbie.我是蟒蛇新手。 Can someone please explain why one would want to define static methods?有人可以解释为什么要定义静态方法吗? Or, why are not all methods defined as static methods?或者,为什么不是所有方法都定义为静态方法?

See this article for detailed explanation.详细解释见这篇文章

TL;DR TL; 博士

1.It eliminates the use of self argument. 1.它消除了self论证的使用。

2.It reduces memory usage because Python doesn't have to instantiate a bound-method for each object instiantiated: 2.它减少了内存使用,因为Python不必为每个实例化的对象实例化一个绑定方法

>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True

3.It improves code readability, signifying that the method does not depend on state of the object itself. 3.它提高了代码的可读性,意味着该方法不依赖于对象本身的状态。

4.It allows for method overriding in that if the method were defined at the module-level (ie outside the class) a subclass would not be able to override that method. 4.它允许方法覆盖,因为如果方法是在模块级别(即在类之外)定义的,子类将无法覆盖该方法。

Static methods have limited use, because they don't have access to the attributes of an instance of a class (like a regular method does), and they don't have access to the attributes of the class itself (like a class method does).静态方法的用途有限,因为它们无权访问类实例的属性(如常规方法那样),也无权访问类本身的属性(如类方法那样) )。

So they aren't useful for day-to-day methods.所以它们对日常方法没有用。

However, they can be useful to group some utility function together with a class - eg a simple conversion from one type to another - that doesn't need access to any information apart from the parameters provided (and perhaps some attributes global to the module.)但是,它们可以用于将一些实用程序函数与一个类组合在一起 - 例如从一种类型到另一种类型的简单转换 - 除了提供的参数之外不需要访问任何信息(可能还有一些全局属性)。 )

They could be put outside the class, but grouping them inside the class may make sense where they are only applicable there.它们可以放在班级之外,但将它们分组在班级内可能有意义,因为它们仅适用于那里。

You can also reference the method via an instance or the class, rather than the module name, which may help the reader understand to what instance the method is related.您还可以通过实例或类而不是模块名称来引用该方法,这可能有助于读者理解该方法与哪个实例相关。

This is not quite to the point of your actual question, but since you've said you are a python newbie perhaps it will be helpful, and no one else has quite come out and said it explicitly.这不是您的实际问题的重点,但是既然您已经说过您是 Python 新手,也许它会有所帮助,并且没有其他人完全出来并明确表示过。

I would never have fixed the above code by making the method a static method.我永远不会通过使方法成为静态方法来修复上述代码。 I would either have ditched the class and just written a function:我要么放弃这个课程,只写一个函数:

def drawSample(samplesize,List):
    sample=random.sample(List,samplesize)
    return sample

Choices=range(100)
print drawSample(5,Choices)

If you have many related functions, you can group them in a module - ie, put them all in the same file, named sample.py for example;如果你有很多相关的函数,你可以将它们组合在一个模块中——即,将它们全部放在同一个文件中,例如,命名为sample.py then然后

import sample

Choices=range(100)
print sample.drawSample(5,Choices)

Or I would have added an __init__ method to the class and created an instance that had useful methods:或者我会在类中添加一个__init__方法并创建一个具有有用方法的实例:

class Sample(object):
'''This class defines various methods related to the sample'''

    def __init__(self, thelist):
        self.list = thelist

    def draw_sample(self, samplesize):
        sample=random.sample(self.list,samplesize)
        return sample

choices=Sample(range(100))
print choices.draw_sample(5)

(I also changed the case conventions in the above example to match the style recommended by PEP 8.) (我还更改了上面示例中的大小写约定以匹配 PEP 8 推荐的样式。)

One of the advantages of Python is that it doesn't force you to use classes for everything. Python 的优点之一是它不会强迫您对所有事情都使用类。 You can use them only when there is data or state that should be associated with the methods, which is what classes are for.只有当有数据或状态应该与方法相关联时才能使用它们,这就是类的用途。 Otherwise you can use functions, which is what functions are for.否则,您可以使用函数,这就是函数的用途。

Why one would want to define static methods ?为什么要定义静态方法

Suppose we have a class called Math then假设我们有一个叫做Mathclass

nobody will want to create object of class Math没有人会想要创建class Math对象
and then invoke methods like ceil and floor and fabs on it.然后在其上调用ceilfloorfabs等方法。

So we make them static .所以我们让它们static

For example doing例如做

>> Math.floor(3.14)

is much better than

>> mymath = Math()
>> mymath.floor(3.14)

So they are useful in some way.所以它们在某种程度上很有用。 You need not create an instance of a class to use them.您无需创建类的实例即可使用它们。

Why are not all methods defined as static methods ?为什么不是所有方法都定义为静态方法

They don't have access to instance variables.他们无权访问实例变量。

class Foo(object):
    def __init__(self):
        self.bar = 'bar'

    def too(self):
        print self.bar

    @staticmethod
    def foo():
        print self.bar

Foo().too() # works
Foo.foo() # doesn't work

That is why we don't make all the methods static.这就是为什么我们不将所有方法都设为静态的原因。

When you call a function object from an object instance, it becomes a 'bound method' and gets the instance object itself is passed in as a first argument.当您从对象实例调用函数对象时,它变成了“绑定方法”,并获取实例对象本身作为第一个参数传入。

When you call a classmethod object (which wraps a function object) on an object instance, the class of the instance object gets passed in as a first argument.当您在对象实例上调用classmethod对象(包装函数对象)时,实例对象的类将作为第一个参数传入。

When you call a staticmethod object (which wraps a function object), no implicit first argument is used.当您调用staticmethod对象(包装函数对象)时,不会使用隐式第一个参数。

class Foo(object):

    def bar(*args):
        print args

    @classmethod
    def baaz(*args):
        print args

    @staticmethod
    def quux(*args):
        print args

>>> foo = Foo()

>>> Foo.bar(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)

>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)

The alternatives to a staticmethod are: classmethod , instancemethod , and function . staticmethod方法的替代方法是: classmethodinstancemethodfunction If you don't know what these are, scroll down to the last section.如果您不知道这些是什么,请向下滚动到最后一部分。 If a staticmethod is better than any of these alternatives, depends on for what purpose it is written.如果staticmethod方法比这些替代方法中的任何一个更好,则取决于它的编写目的。

advantages of the Python static method Python静态方法的优点

  • If you don't need access to the attributes or methods of the class or instance, a staticmethod is better than a classmethod or instancemethod .如果你不需要访问属性或类或实例的方法,一个staticmethod比一个更好的classmethodinstancemethod That way it is clear (from the @staticmethod decorator) that the class' and instance's state is not read or modified.这样很明显(从@staticmethod装饰器)类和实例的状态没有被读取或修改。 However, using a function makes that distinction even clearer (see disadvantages).但是,使用function会使这种区别更加清晰(请参阅缺点)。
  • The call signature of a staticmethod is the same as that of a classmethod or instancemethod , namely <instance>.<method>(<arguments>) . staticmethod方法的调用签名与classmethodinstancemethod <instance>.<method>(<arguments>)的调用签名相同,即<instance>.<method>(<arguments>) Hence it can easily be replaced by one of the three if that is needed later on or in a derived class.因此,如果稍后或在派生类中需要,可以很容易地将其替换为三者之一。 You can't do that with a simple function .你不能用一个简单的function来做到这一点。
  • A staticmethod can be used instead of a function to make clear that it subjectively belongs to a class and to prevent namespace conflicts.可以使用staticmethod方法代替function来明确它主观上属于一个类并防止命名空间冲突。

disadvantages of the Python static method Python静态方法的缺点

  • It cannot access attributes or methods of the instance or class.它不能访问实例或类的属性或方法。
  • The call signature of a staticmethod is the same as that of a classmethod or instancemethod . staticmethod的调用签名与classmethodinstancemethod的调用签名相同。 This masks the fact that the staticmethod does not actually read or modify any object information.这掩盖了staticmethod实际上不读取或修改任何对象信息的事实。 This makes code harder to read.这使得代码更难阅读。 Why not just use a function ?为什么不直接使用function
  • A staticmethod is difficult to re-use if you ever need to call it from outside the class/instance where it was defined.如果您需要从定义它的类/实例外部调用staticmethod则很难重用它。 If there is any potential for re-use, a function is the better choice.如果有任何重用的潜力, function是更好的选择。
  • The staticmethod is seldom used, so people reading code that includes one may take a little longer to read it. staticmethod方法很少使用,因此人们阅读包含一个的代码可能需要更长的时间来阅读它。

alternatives to a static method in Python Python 中静态方法的替代方法

To address discuss the advantages of the staticmethod , we need to know what the alternatives are and how they differ from each other.为了讨论staticmethod的优点,我们需要知道替代方法是什么以及它们之间有何不同。

  • The staticmethod belongs to a class but cannot access or modify any instance or class information. staticmethod属于一个类,但不能访问或修改任何实例或类信息。

There are three alternatives to it:它有以下三种替代方案:

  • The classmethod has access to the caller's class. classmethod可以访问调用者的类。
  • The instancemethod has access to the caller's instance and its class. instancemethod可以访问调用者的实例及其类。
  • The function has nothing to do with classes.function与类无关。 It is the closest in capability to the staticmethod .它在功能上最接近于staticmethod

Here's what this looks like in code:这是代码中的样子:

# function
# has nothing to do with a class
def make_cat_noise(asker_name):
    print('Hi %s, mieets mieets!' % asker_name)

# Yey, we can make cat noises before we've even defined what a cat is!
make_cat_noise('JOey')  # just a function

class Cat:
    number_of_legs = 4

    # special instance method __init__
    def __init__(self, name):
        self.name = name

    # instancemethod
    # the instance (e.g. Cat('Kitty')) is passed as the first method argument
    def tell_me_about_this_animal(self, asker_name):
        print('Hi %s, This cat has %d legs and is called %s'
              % (asker_name, self.number_of_legs, self.name))

    # classmethod
    # the class (e.g. Cat) is passed as the first method argument
    # by convention we call that argument cls
    @classmethod
    def tell_me_about_cats(cls, asker_name):
        print("Hi %s, cats have %d legs."
              % (asker_name, cls.number_of_legs))
        # cls.name  # AttributeError because only the instance has .name
        # self.name  # NameError because self isn't defined in this namespace

    # staticmethod
    # no information about the class or the instance is passed to the method
    @staticmethod
    def make_noise(asker_name):
        print('Hi %s, meooow!' % asker_name)
        # class and instance are not accessible from here

# one more time for fun!
make_cat_noise('JOey')  # just a function

# We just need the class to call a classmethod or staticmethod:
Cat.make_noise('JOey')  # staticmethod
Cat.tell_me_about_cats('JOey')  # classmethod
# Cat.tell_me_about_this_animal('JOey')  # instancemethod -> TypeError

# With an instance we can use instancemethod, classmethod or staticmethod
mycat = Cat('Kitty')  # mycat is an instance of the class Cat
mycat.make_noise('JOey')  # staticmethod
mycat.tell_me_about_cats('JOey')  # classmethod
mycat.tell_me_about_this_animal('JOey')  # instancemethod

static methods are great because you don't have to declare an instance of the object to which the method belongs.静态方法很棒,因为您不必声明该方法所属的对象的实例。

python's site has some great documentation on static methods here: python 的站点在这里有一些关于静态方法的很好的文档:
http://docs.python.org/library/functions.html#staticmethod http://docs.python.org/library/functions.html#staticmethod

In my estimation, there is no single performance benefit of using @staticmethod s compared to just defining the function outside of and separate from the class it would otherwise be a @staticmethod of.据我估计,有使用没有单一的性能优势@staticmethod标准相比较,只是从定义类的功能之外,单独它本来是一个@staticmethod的。

The only thing I would say justifies their existence is convenience.我要说的唯一证明它们存在的理由是方便。 Static methods are common in other popular programming languages, so why not python?静态方法在其他流行的编程语言中很常见,那么为什么 python 不呢? If you want to create a function with behavior that is very closely associated with the class you are creating it for but it doesn't actually access/modify the internal data of an instance of the class in a way that justifies conceptualizing it as a typical method of that class then slap a @staticmethod above it and anyone reading your code will immediately learn a lot about the nature of the method and its relationship to the class.如果您想创建一个行为与您为其创建的类非常密切相关的函数,但它实际上并没有以一种证明将其概念化为典型的方式访问/修改类的实例的内部数据该类的方法然后在它上面加上一个@staticmethod ,任何阅读您代码的人都会立即了解该方法的性质及其与该类的关系。

One thing I occasionally like to do is place functionality that my class uses internally a lot into private @staticmethod s.我偶尔喜欢做的一件事是将我的类在内部大量使用的功能放入私有@staticmethod That way I do not clutter the API exposed by my module with methods that no one using my module would ever need to see let alone use.这样我就不会将模块公开的 API 与使用我的模块的人都不需要看到的方法混在一起,更不用说使用了。

Static methods have almost no reason-to-be in Python.在 Python 中几乎没有理由使用静态方法。 You use either instance methods or class methods.您可以使用实例方法或类方法。

def method(self, args):
    self.member = something

@classmethod
def method(cls, args):
    cls.member = something

@staticmethod
def method(args):
    MyClass.member = something
    # The above isn't really working
    # if you have a subclass

Because namespacing functions is nice (as was previously pointed out):因为命名空间函数很好(如前所述):

  1. When I want to be explicit about methods that don't change the state of the object, I use static methods.当我想明确不改变对象状态的方法时,我使用静态方法。 This discourages people on my team to start changing the object's attributes in those methods.这不鼓励我团队中的人开始在这些方法中更改对象的属性。

  2. When i refactor really rotten code, I start by trying to make as many methods @staticmethod as possible.当我重构非常烂的代码时,我首先尝试创建尽可能多的方法@staticmethod This allows me then to extract these methods into a class - though I agree, this is rarely something I use, it did came in helpful a few times.这允许我将这些方法提取到一个类中 - 尽管我同意,这很少使用,但它确实有用过几次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Python中使用&#39;with ... as&#39;语句有什么好处? - What's the advantage of using 'with .. as' statement in Python? 使用Python Virtualbox API有什么好处? - What is the advantage of using Python Virtualbox API? 在 __iter__() 中使用 yield 有什么好处? - What's the advantage of using yield in __iter__()? 使用 Flasks app.logger 有什么好处? - What is the advantage of using Flasks app.logger? 在运行时创建类时,使用`exec`而不是`type()`有什么好处? - What is the advantage in using `exec` over `type()` when creating classes at runtime? 在 psycopg2 中对 PostgreSQL 查询使用多个游标有什么好处? - What is the advantage of using multiple cursors in psycopg2 for PostgreSQL queries? 使用命令行运行python脚本有什么优势? - What is the advantage of running python script using command line? 在带有 Tensorflow 张量的 Keras 模型中使用 InputLayer(或 Input)有什么好处? - What is the advantage of using an InputLayer (or an Input) in a Keras model with Tensorflow tensors? 使用 mode() 将列中的 nans 替换为 Dtype=object 有什么好处? - What is the advantage of using mode() to replace nans in columns with Dtype=object? 如果在 if-else 条件下使用 assert 有什么好处? - What is the advantage if any of using assert over an if-else condition?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM