Python中的'self'用法 - 一个菜鸟在努力理解它

0 投票
3 回答
1265 浏览
提问于 2025-04-16 00:55

我有一个简单的套接字类:MySocketLib.py ..

import socket

class socklib():
    def create_tcp_serversocket(self,port):
        serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        serversocket.bind((socket.gethostname(), port))
        serversocket.listen(5) 
        return serversocket

    def send_msg(self, sock, msg, msglen):
         ... blah blah ...  

    def recv_msg(self, sock, msglen):
         ... blah blah .... 

我的主文件是Server.py,内容如下:

import MySocketLib

class serverclass(): 

    def __init__(self,port):
        self.servsock = 0
        self.port = port

    def run(self):
        self.servsock = self.create_tcp_serversocket(self.port)
        (clientsock, address) = self.servsock.accept() # ERROR: 'SELF' not defined
        ... blah blah ... 

#############################
###   Main startup code

if __name__ == '__main__':
    server = serverclass(2000) # server is on port 2000
    server.run()

我一直遇到下面的错误:

File "D:\CodeLearn\Server.py", line 14, in serverclass
(clientsock, address) = self.servsock.accept()
NameError: name 'self' is not defined

我对“self”这个概念总是搞不清楚。有时候它看起来是必须的,有时候又不需要。为什么在这里我还需要定义'自我',它不是一个Python的关键字吗?


谢谢大家……问题确实是因为制表符和空格的设置。我使用的是Eclipse,在偏好设置中我把“编辑器”的选项设置为在缩进时使用空格。

3 个回答

0

你的缩进有问题,所以 __init__()run() 被当成了顶层函数来理解——这样就没有自动的 self 参数了。你需要这样做:

class serverclass:

    def __init__(self,port):
        self.servsock = 0
        self.port = port

    def run(self):
        self.servsock = self.create_tcp_serversocket(self.port)
        (clientsock, address) = self.servsock.accept() # ERROR: 'SELF' not defined
        ... blah blah ... 
2

这可能是缩进错误。
文件

"D:\CodeLearn\Server.py", line 14, in serverclass
这意味着
(clientsock, address) = self.servsock.accept()
并不在 run 函数里面,而是在 serverclass 这个类里面。

4

在Python代码中不要使用制表符,记得把你的编辑器设置成只用空格。

self 不是Python的关键字,而是一种约定。它是你在使用的类的“实例”的常用名称。举个例子:

class X:
    def __init__(self, v): self.v = v

a = X(1)
b = X(2)
print a.v, b.v

当这段代码运行时,Python会为两个 X 的实例分配内存,分别给 ab。如果没有像 self 这样的东西,你就得写:

a = X()
a.v = 1
b = X()
b.b = 2
print a.v, b.v

这样会出错,因为你写了 b.b 而不是 b.v。而且,调用方法的方式会显得很糟糕:

class X:
    def set(v): ???.v = v

你怎么说“访问在 X__init__ 中分配的 v 的引用”?

一种解决方法是把实例引用(指向为 X 分配的内存的指针)作为参数传递:

class X:
    def set(a, v): a.v = v

a.set(a, 1) # Holy ugly!

每个人都会用不同的名称,这样就会违反DRY原则,搞得一团糟。所以Python的做法是:

class X:
    def set(self, v): self.v = v

a.set(1) # while "set" runs, "self" == "a"
b.set(2) # while "set" runs, "self" == "b"

不过,我不明白为什么上面的代码会出错。显然 self 是定义过的,否则在你的 run() 方法的第一行就会出错。所以我猜是你在缩进时混用了空格和制表符,这让Python感到困惑,它看到的是:

def run(self):
    self.servsock = self.create_tcp_serversocket(self.port)
(clientsock, address) = self.servsock.accept() # ERROR: 'SELF' not defined

然后它会在解析类定义时尝试执行 self.servsock.accept()。那个时候,实例还不存在(类还没创建!),所以 self 也不可用。

总结:永远不要混用制表符和空格。

撰写回答