更高效地调用Python中的方法

2 投票
2 回答
601 浏览
提问于 2025-04-16 22:35

我是一名新手,正在学习《Learn Python the Hard Way》这本书。

这个练习的目的是写一个单词扫描器,能够通过提供的单元测试的nosetests。

在运行nosetests时,我遇到了一个错误:

`TypeError: unbound method scan() must be called with lexicon instance as first argument (got str instance instead)`

提供的测试

from nose.tools import *
from ex48 import lexicon

def test_directions():
    assert_equal(lex.scan("north"), [('direction', 'north')])
    result = lex.scan("north south east")
    assert_equal(result, [('direction', 'north'),
                          ('direction', 'south'),
                          ('direction', 'east)])

经过一些调查,我发现这里有个用户也在做同样的练习:

nosetests, python

python 变量, 类

那里的回答建议在单元测试中实例化(也就是创建一个对象)这个方法。所以我做了以下修改,并在文件ex48.py中写了我的类,结果通过了nosetests。

修改后的测试

from nose.tools import *
from ex48 import lexicon


def test_directions():
    lex = lexicon("north")
    assert_equal(lex.scan("north"), [('direction', 'north')])
    lex = lexicon("north south east")
    result = lex.scan("north south east")
    assert_equal(result, [('direction', 'north'),
                          ('direction', 'south'),
                          ('direction', 'east')]) 

ex48.py - 扫描器

class lexicon(object):

    def __init__(self, data):
        #nosetests fails me if I don't put in some dummy
        # __init__ function with a dummy line, not sure why.
    self.direction = data

    def scan(self, data):
        split_data = data.split()
        directions = ['north', 'south', 'east', 'west']
        data_reply = []
        #for loop for the length of the list
        for split_data_item in split_data:
            #If data is in the directions list
            if split_data_item in directions:
                #Add [('direction', data)] to a dict
                data_reply.append(('direction', split_data_item))

        #Return the list
        return data_reply

我不确定这个单元测试是否应该被修改。我在这里找到了一些关于“直接实例化一个对象”的线索:

Python: 调用一个方法是否会“直接”实例化对象?

但我不确定这是否适用。扫描器能否自己实例化,还是说提供的单元测试是个“陷阱”问题,必须被修改?

2 个回答

4

在《艰难学Python》的在线版本中,他们提到:

def test_directions():
    assert_equal(lexicon.scan("north"), [('direction', 'north')])
    result = lexicon.scan("north south east")
    assert_equal(result, [('direction', 'north'),
                          ('direction', 'south'),
                          ('direction', 'east')])

对于测试来说,这意味着你不需要一个词汇类,而是需要一个包含扫描功能的lexicon.py文件来进行测试。

而且这里的“instantiating”是指我正在创建这个类的一个实例。

2

你应该保持测试的原样,然后在扫描方法上加一个 @staticmethod 装饰器。这样的话,你就可以直接从类里调用这个方法,而不需要先创建一个对象。

class lexicon(object):

   @staticmethod
   def scan(data):
      #do the stuff here

撰写回答