iT邦幫忙

0

python @staticmethod 使用場合

  • 分享至 

  • xImage

最近在學習寫 telegram bot,在把教學的語法包裝成一個 class 的時候遇到了一些問題

import logging
from telegram import Update
from telegram.ext import Updater, MessageHandler, CommandHandler, CallbackContext, Filters


class Bot:

    @staticmethod
    def start(update: Update, context: CallbackContext):
        context.bot.send_message(chat_id=update.effective_chat.id, text="這是一個機器人,輸入 /help 獲得更多使用說明")

    @staticmethod
    def help(update: Update, context: CallbackContext):
        context.bot.send_message(chat_id=update.effective_chat.id, text="")

    @staticmethod
    def unknown(update: Update, context: CallbackContext):
        context.bot.send_message(chat_id=update.effective_chat.id, text="未知的指令,輸入 /help 獲得更多使用說明")

    def __init__(self):
        self.updater = Updater(token='example')
        self.dispatcher = self.updater.dispatcher
        self.init_command()
        logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
        self.updater.start_polling()

    def init_command(self):
        self.dispatcher.add_handler(CommandHandler('start', self.start))  # 處理 start command
        self.dispatcher.add_handler(CommandHandler('help', self.help))  # 處理 help command
        self.dispatcher.add_handler(MessageHandler(Filters.command, self.unknown))  # 處理所有上述以外的 command

if __name__ == "__main__":
    bot = Bot()

為什麼在這邊 @staticmethod 這個 decorator 是必要的?
如果把 @staticmethod 取消後會讓 add_handler 裡面的 self.start/help/unknown 出現錯誤,錯誤訊息如下

Expected type '(Update, Any) -> Any' (matched generic type '(Update, CCT) -> RT'), got '(context: CallbackContext) -> None' instead 

可以解釋為什麼當 class 調用內部的函數時會需要宣告成 staticmethod 呢?

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
froce
iT邦大師 1 級 ‧ 2022-12-29 23:50:49
最佳解答

因為如果取消 @staticmethod ,那物件的方法的第一個參數就是self,像下面這樣改試試吧

class Bot:
    def start(self, update: Update, context: CallbackContext):
        context.bot.send_message(chat_id=update.effective_chat.id, text="這是一個機器人,輸入 /help 獲得更多使用說明")

    def help(self, update: Update, context: CallbackContext):
        context.bot.send_message(chat_id=update.effective_chat.id, text="")

    def unknown(self, update: Update, context: CallbackContext):
        context.bot.send_message(chat_id=update.effective_chat.id, text="未知的指令,輸入 /help 獲得更多使用說明")

    def __init__(self):
        self.updater = Updater(token='example')
        self.dispatcher = self.updater.dispatcher
        self.init_command()
        logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
        self.updater.start_polling()

    def init_command(self):
        self.dispatcher.add_handler(CommandHandler('start', self.start))  # 處理 start command
        self.dispatcher.add_handler(CommandHandler('help', self.help))  # 處理 help command
        self.dispatcher.add_handler(MessageHandler(Filters.command, self.unknown))  # 處理所有上述以外的 command

是說這邊用 staticmethod 實在不太對。

至於什麼時候用 staticmethod ...
https://ji3g4zo6qi6.medium.com/python-tips-5d36df9f6ad5
我個人是很少用,classmethod 比較常用。

看更多先前的回應...收起先前的回應...

你好,依照上面的寫法可以成功跑過,但是 IDE 會提示那幾個 function 應該是 static,可以為解釋一下為什麼 IDE 會這樣判斷嗎?

因為我是希望把機器人會用到的指令都包在同一個 class 裡面

froce iT邦大師 1 級 ‧ 2022-12-30 18:04:46 檢舉

IDE的提示貼出來我看看。

https://ithelp.ithome.com.tw/upload/images/20221230/20141552nCRYmmxja0.png

re.Zero iT邦研究生 5 級 ‧ 2022-12-30 21:00:37 檢舉

@cave_rabbit: 看圖片,我猜是這個的關係: Why does PyCharm propose to change method to static?
(因為圖片內容訊息太少 + 我去翻源碼也看不出所以然~所以用猜的~坐等 froce 大有空時給出的見解~)

froce iT邦大師 1 級 ‧ 2022-12-30 21:09:05 檢舉

應該就是stack overflow那篇說的,一個物件方法的第一個參數,你不是用一般method的self,也不是用classmethod的cls,那IDE就認為你用的是staticmethod,而提示你。

總之依你的場景用不到 staticmethod/classmethod。

我要發表回答

立即登入回答