class MyHTMLParser(HTMLParser):
start = False;
counter = 0;
...
这并不像你认为的那样!
在 Java、C# 或类似语言中,类似代码所做的是声明称为MyHTMLParser
all 的对象类具有start
初始值为False
和counter
初始值为 的属性0
。
在 Python中,类也是对象。它们有自己的属性,就像所有其他对象一样。所以上面在 Python 中所做的是创建一个名为 的类对象MyHTMLParser
,其属性start
设置为False
,属性counter
设置为0
。1
要记住的另一件事是,没有任何方法可以对裸名称进行分配,例如start = True
在对象上设置属性。它总是设置一个名为 的变量start
。2
MyHTMLParser
因此,您的类不包含在您的任何实例上设置任何属性的代码;类主体中的代码是设置类对象本身的属性,而其中的代码handle_starttag
是设置局部变量,然后当它们超出范围时将其丢弃。
出于类似的原因,您的代码正在从名为(您从未设置过)handle_data
的局部变量中读取。start
在 Python 中,如果不指定要在哪个对象中查找属性,就无法读取属性。barestart
总是指代变量,无论是在本地函数范围内还是在某些外部范围内。您需要self.start
读取对象的start
属性self
。
请记住,def
定义方法的块没有什么特别之处,它是一个和其他任何函数一样的函数。只有稍后,当该函数恰好存储在类对象的属性中时,该函数才能被归类为方法。因此,该self
参数的行为与任何其他参数相同,实际上也与任何其他名称相同。它不必被命名self
(尽管这是一个明智的约定),并且它没有特殊的特权使裸名的读取和写入查找self
.
所以:
不要在类块中用它们的初始值来定义你的属性;这是由类的所有实例共享的值,而不是每个实例的属性。实例属性只有在您引用特定实例后才能被初始化;最常见的是在__init__
方法中完成,只要对象存在就会调用该方法。
您必须指定要在哪个对象中读取或写入属性。这始终适用于任何情况。特别是,您通常将方法内的属性称为self.attribute
.
应用它(并消除在 Python 中不需要的分号):
class MyHTMLParser(HTMLParser):
def __init__(self):
start = False
counter = 0
def handle_starttag(self, tag, attrs):
if(tag == 'TBODY'):
self.start = True
self.counter += 1
def handle_data(self, data):
if (self.start == True):
print data
1方法handle_starttag
和handle_data
函数也只不过是函数,它们恰好是用作类的对象的属性。
2通常是局部变量;如果您已声明start
为global
,nonlocal
则它可能是外部变量。但它绝对不是您碰巧在附近的某个对象的属性,即使该其他对象绑定到 name self
。