You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Selenium PageObjects框架报错:TypeError: 'tuple' object is not callable 求助

问题分析与解决方案

你遇到的TypeError: 'tuple' object is not callable错误,核心原因是Card类中属性名和方法名重名了,导致方法被属性覆盖,最终调用的是一个不可调用的元组对象。

具体原因拆解

看你的Card类代码:

class Card:
    def __init__(self,selenium_object):
        self.selenium_object = selenium_object
        self.name = Locator.CARD_NAME  # 这里赋值的是定位器元组
        self.description = Locator.CARD_DESCRIPTION  # 同样是元组
        self.do = Locator.CARD_DO_BUTTON  # 重点:这里把元组赋值给了self.do
        self.cancel = Locator.CARD_CANCEL_BUTTON
        self._load()
    
    def do(self):  # 这里定义的do方法,会被__init__里的self.do元组覆盖
        self.selenium_object.find_element(*self.do).click()
    
    def cancel(self):  # 同理,cancel方法也会被覆盖
        self.selenium_object.find_element(*self.cancel).click()

当你实例化Card对象时,__init__方法会先执行,把Locator.CARD_DO_BUTTON这个元组赋值给self.do。之后定义的do()方法根本不会成为实例的方法——因为属性已经占用了这个名称。所以当你调用todos[0].do()时,实际上是在尝试调用一个元组,自然会抛出"tuple不可调用"的错误。

修复方案

把定位器属性的名称和方法名称区分开,比如给定位器属性加上下划线前缀,避免和方法名冲突:

修改后的Card类代码:

class Card:
    def __init__(self,selenium_object):
        self.selenium_object = selenium_object
        # 定位器属性改用下划线前缀,避免和方法名冲突
        self._name_locator = Locator.CARD_NAME
        self._description_locator = Locator.CARD_DESCRIPTION
        self._do_locator = Locator.CARD_DO_BUTTON
        self._cancel_locator = Locator.CARD_CANCEL_BUTTON
        self._load()
    
    def do(self):
        self.selenium_object.find_element(*self._do_locator).click()
    
    def cancel(self):
        self.selenium_object.find_element(*self._cancel_locator).click()
    
    def _load(self):
        # 加载元素文本时使用修改后的定位器属性
        self.name = self.selenium_object.find_element(*self._name_locator).text
        self.description = self.selenium_object.find_element(*self._description_locator).text
    
    def __repr__(self):
        return f'Card(name ="{self.name}", description = "{self.description}")'

额外优化建议

  • 你可以把定位器的命名统一风格,比如都用xxx_locator的格式,这样更清晰,也能避免类似的命名冲突问题。
  • 另外,在Todo类中,你直接用self.webdriver.find_element(*self.name),其实可以复用PageElement类里的find_element方法,写成self.find_element(self.name),这样代码更简洁,也符合PageObject模式的封装思想。

内容的提问来源于stack exchange,提问作者Bruno Lorena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 15:48:12