简体   繁体   中英

How to instance a class in a loop in Python

I have a simple chat application with server and client code in Python. In the server side the class Client defines the following

class Client(object):
    def __init__(self, socket, address):
     self.sock = socket
     self.addr = address
     self.room = None
     self.name = None
     self._is_online = True
     thread = threading.Thread(target=self.run, args=())
     thread.daemon = True
     thread.start()

As you can see the server handles every client as a different thread. On the main thread the server runs in a always-true loop

while True:
(ready_to_read, _, _) = select.select([server_sckt] + [Client.sock for Client in clients], [], [])
for connection in ready_to_read:
    if connection == server_sckt:
        (connection, address) = server_sckt.accept()
        clients.append( Client(connection, address) )

clients is the list containing all Client objects. The problem comes in the second loop iteration.

Traceback (most recent call last):
 File "servidor_class.py", line 215, in <module>
  clients.append( Client(connection, address) )
TypeError: 'Client' object is not callable

So it's clear I'm not getting pythonic OOP way to declare each instance.

I've looked another related questions:

  1. Creating object instances in a loop with independent handling
  2. Python creating multiple instances for a single object/class

But I'm still not seeing my mistake instancing, sure it's in front of me. Without appending to a list seems to work but main server functionalities like send message to all online people or check if username if already used doesn't work.

In Python 2, list comprehensions leak the control variable: See this question

The problem is a few lines above where the exception actually happens in the select line

#                                                                      | Here
#                                                                      v
(ready_to_read, _, _) = select.select([server_sckt] + [Client.sock for Client in clients], [], [])

In the list comprehension you redefine what Client means. It becomes an instance of the Client class. So when you try to create another instance using an existing instance instead of a class, it raises an exception.

Change the list comprehension part to

#                | notice the lower case.
#                v
[client.sock for client in clients]

Or anything else besides Client

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM