首页  >  问答  >  正文

python @property @staticmethod

这两个东西在什么情况下用

PHP中文网PHP中文网2741 天前778

全部回复(1)我来回复

  • 伊谢尔伦

    伊谢尔伦2017-04-18 09:06:34

    简单来说

    • @property 是Python 中用来取代getter/setter 的decorator,他可以包装、处理、封装类属性,也可以很方便地建立唯读属性,重点是他维持了介面的简单。因为我们能够很直觉的存取属性而不必使用冗赘地使用 get_XXXset_XXX 这类的 getter/setter。我本来也想打一篇完整的说明,但是下笔思考后觉得不够全面,所以还是先放弃待日后补齐,如果有其他高手很了解这一块的,欢迎给发问者和小弟我一点意见。 @property 是 Python 中用來取代 getter/setter 的 decorator,他可以包裝、處理、封裝類屬性,也可以很方便地建立唯讀屬性,重點是他維持了 介面的簡單。因為我們能夠很直覺的存取屬性而不必使用冗贅地使用 get_XXXset_XXX 這類的 getter/setter。我本來也想打一篇完整的說明,但是下筆思考後覺得不夠全面,所以還是先放棄待日後補齊,如果有其他高手很了解這一塊的,歡迎給發問者和小弟我一點意見。

    • @staticmethod 我覺得是 沒什麼實際作用 非必要 的 decorator (這點如果大家有不同意見,歡迎討論,我滿想討論這個的)


    (這次的回答比較艱澀一點,如果覺得繁體看起來吃力,可以用 browser 轉成簡體後看...)

    @staticmethod

    特色與使用情境

    先講 staticmethod 好了,被 staticmethod 修飾的 method 並不會接收特殊的第一項引數 (一般的 instance method 和被 classmethod 修飾過的 類別方法 分別會接受實例和類別的參考作為第一項參數),這讓靜態方法就像是個一般的 function,只是他剛好被定義在 class 裡而不是直接定義在 module level。

    所以他的 使用情境就是: 當某個類裡面的函數不需要像是 self 或是 cls 等實例或類的參考時,使用靜態方法可以比較簡明且有效率地完成工作。

    1. 簡明的部分在於不需要多接收一個無關緊要的引數

    2. 效率在於一般的實例方法是 bound method (是個 object) 且是在我們要使用他的時候才生成,這會花上多一點點的 cost,而靜態方法並不會

    實用/不實用?

    但我覺得他並不實用,首先與類有直接關係的函數我們可以用 classmethod 就好,在代碼之中我們依靠第一項引數提供的 class 參考能夠完成與類有關的操作 (比如說 __init__ 的替代物 或是 做為一個調度更多子 staticmethod 的上層方法)。

    若非與類有關(而又與實例無關),那我們需要類別靜態方法的目的,我暫時只想的到一個: 為了調用上能夠有一個抽象的層級 (沒錯,我說的就是 namespace) 而此函數雖然不會直接接觸類但是卻與類有關。

    但是在 Python 之中,使用 namespace

  • 🎜@staticmethod 我觉得是没什么实际作用 非必要的decorator (这点如果大家有不同意见,欢迎讨论,我满想讨论这个的)🎜
    🎜(这次的回答比较艰涩一点,如果觉得繁体看起来吃力,可以用 browser 转成简体后看...)🎜

    @staticmethod

    特色与使用情境

    🎜先讲staticmethod 好了,被staticmethod 修饰的method 并不会接收特殊的第一项引数(一般的instance method 和被classmethod 修饰过的类别方法 分别会接受实例和类别的参考作为第一项参数),这让静态方法就像是个一般的function,只是他刚好被定义在class 里而不是直接定义在module level。 🎜 🎜所以他的使用情境就是: 当某个类里面的函数不需要像是self 或是cls 等实例或类的参考时,使用静态方法可以比较简明且有效率地完成工作。 🎜
      🎜🎜简明的部分在于不需要多接收一个无关紧要的引数🎜 🎜🎜效率在于一般的实例方法是 bound method (是个 object) 且是在我们要使用他的时候才生成,这会花上多一点点的 cost,而静态方法并不会🎜

    实用/不实用?

    🎜但我觉得他并不实用,首先与类有直接关系的函数我们可以用classmethod 就好,在代码之中我们依靠第一项引数提供的class 参考能够完成与类有关的操作(比如说__init__ 的替代物或是做为一个调度更多子staticmethod 的上层方法)。 🎜 🎜若非与类有关(而又与实例无关),那我们需要类别静态方法的目的,我暂时只想的到一个: 为了调用上能够有一个抽象的层级(没错,我说的就是namespace ) 而此函数虽然不会直接接触类但是却与类有关。 🎜 🎜但是在Python 之中,使用namespace 是很容易的事情,我们不如将原先想要定义成静态方法的函数定义在module 层级,且尽可能地放在有关类别的附近,我想就非常足够了(Luciano Ramalho 的观点)。 🎜

    反思

    就在我打完上面这段之后,我特意看了一次Julien Danjou 的一篇超棒的文章:
    The definitive guide on how to use static, class or abstract methods in Python
    我强力推荐任何想弄清楚Python method 的人看这篇文章。

    这篇文章提出了两点 staticmethod 的优点,第一点我在上面已经有提到了,静态方法比起实例方法来的简明与有效率。第二点是静态方法 staticmethod 的優點,第一點我在上面已經有提到了,靜態方法比起實例方法來的簡明與有效率。第二點是靜態方法 雖然與類無關但是屬於類的 ,這代表他可以客製化地為類服務。這有點難懂,我們看一個例子好了( Julien Danjou 文章中例子):

    class Pizza(object):
        @staticmethod
        def mix_ingredients(x, y):
            return x + y
     
        def cook(self):
            return self.mix_ingredients(self.cheese, self.vegetables)

    我們想像一下,如果我們把 mix_ingredients 定義在 module level,那當我們在處理繼承 Pizza 的子類時,勢必無法藉由改動 mix_ingredients 來更動 mix ingredients 的行為 (因為該函數有別的類在使用),那我們只好複寫 cook 了。

    這個理由有一點點讓我改觀,起碼他指出了一個靜態方法跟一般方法的最大不同,靜態方法是單屬於某一類的

    不過我還是比較堅持原先的想法,因為也許 mix_ingredients 可以寫得更好,又或者是對於 Pizza 這種非抽象類別根本是不要去繼承他的,又或是繼承的時候複寫方法是不好的,甚至我可以覺得更動 mix_ingredients 跟更動 cook 同樣都是個負擔。

    小結

    以上都是 我覺得,也許哪一天 staticmethod虽然与类无关但是属于类的

    ,这代表他可以客制化地为类服务。这有点难懂,我们看一个例子好了( Julien Danjou 文章中例子):
    rrreee

    我们想像一下,如果我们把mix_ingredients 定义在module level,那当我们在处理继承Pizza 的子类时,势必无法藉由改动mix_ingredients< /code> 来更动mix ingredients 的行为(因为该函数有别的类在使用),那我们只好复写cook 了。 这个理由有一点点让我改观,起码他指出了一个静态方法跟一般方法的最大不同,

    静态方法是单属于某一类的🎜。 🎜 🎜不过我还是比较坚持原先的想法,因为也许mix_ingredients 可以写得更好,又或者是对于Pizza 这种非抽象类别根本是不要去继承他的,又或是继承的时候复写方法是不好的,甚至我可以觉得更动mix_ingredients 跟更动cook 同样都是个负担。 🎜 🎜小结🎜 🎜以上都是 🎜我觉得🎜,也许哪一天 staticmethod 让我真正优雅地派上用场了,我可能会承认今天我愚昧而肤浅的认识吧。至于你呢? 我觉得你可以有自己的想法,只要你在了解够多的情况下还能说服自己,那我觉得没有任何立场是错误的 :)🎜 🎜 🎜🎜我回答过的问题🎜: Python-QA🎜

    回复
    0
  • 取消回复