Python按引用访问对象/需要标记

1 投票
2 回答
1412 浏览
提问于 2025-04-16 00:07

我需要从标准输入中获取数据,并创建一个对象。

这些数据大约有5到10行。每一行都有一个进程号和一个IP地址或者一个哈希值。比如说:

pid=123 ip=192.168.0.1 - some data
pid=123 hash=ABCDEF0123 - more data
hash=ABCDEF123 - More data
ip=192.168.0.1 - even more data

我想把这些数据放到一个类里面,像这样:

class MyData():
  pid = None
  hash = None
  ip = None
  lines = []

我需要能够通过IP、哈希值或者进程号来查找这个对象。

比较棘手的是,标准输入中会有多个数据流交错在一起。(可能会有成百上千个进程同时在写数据。)

我已经有正则表达式可以提取出我需要的进程号、IP和哈希值,但我该如何通过这些值来访问对象呢?

我想的办法是这样做:

myarray = {}

for each line in sys.stdin.readlines():
  if pid and ip:  #If we can get a PID out of the line
     myarray[pid] = MyData().pid = pid #Create a new MyData object, assign the PID, and stick it in myarray accessible by PID.
     myarray[pid].ip = ip #Add the IP address to the new object
     myarray[pid].lines.append(data) #Append the data

     myarray[ip] = myarray[pid] #Take the object by PID and create a key from the IP.
  <snip>do something similar for pid and hash, hash and ip, etc...</snip>

这样我就得到了一个数组,里面有两个键(一个是进程号,一个是IP),它们都指向同一个对象。但是在下一次循环中,如果我找到(比如说)一个IP和哈希值,然后执行:

myarray[hash] = myarray[ip]

结果是假的:

myarray[hash] == myarray[ip]

希望这样说清楚了。我不太愿意承认,但在很久以前的VB时代,我记得可以通过引用来处理对象,而不是通过值。在Python中有没有类似的东西?还是说我根本就没有搞对?

2 个回答

2

Python 里只有引用。

只需要创建一次对象,然后把它同时添加到所有相关的键里。

class MyData(object):
  def __init__(self, pid, ip, hash):
    self.pid = pid
     ...

for line in sys.stdin:
  pid, ip, hash = process(line)
  obj = MyData(pid=pid, ip=ip, hash=hash)
  if pid:
    mydict[pid] = obj
  if ip:
    mydict[ip] = obj
  if hash:
    mydict[hash] = obj
2

创建两个独立的字典(别叫它们数组!),一个叫 byip,另一个叫 byhash。为什么要把所有东西挤在一起,还要冒着冲突的风险呢?

顺便说一下,你绝对不能把下面这两行代码放在一起:

myarray[hash] = myarray[ip]
assert not(myarray[hash] == myarray[ip])

为了让 assert 成立,你必须在中间做点别的事情(也就是要去改变那个名字不太合适的 myarray)。

再顺便提一句,在Python中,赋值总是通过引用来处理对象的。如果你想要一个副本,你必须明确要求。

撰写回答