Python OO problem

2

Ho iniziato a imparare Python ieri e mi sono imbattuto in un problema. Mi piace sentire alcuni pensieri su di esso.

Come esercizio, ho deciso di costruire un chatserver. Come parte dell'esercizio, volevo scrivere un codice di ereditarietà.

Class A
  def foo
    print "foo"

Class B(A)
  def bar
    print "bar"

c = B()
c.foo()
>>> prints: foo

ok, a me sembra un'eredità di base molto normale (per favore fatemi sapere se non siete d'accordo). Quindi, per tornare al mio chatserver, ho pensato che sarebbe stato bello estendere il socket e trasformarlo in un socket di chat. La prima cosa che volevo fare è aggiungere un attributo chiamato nickname (importante in una chat). Oh, e ho pensato di usare select come soluzione di threading perché sembrava altamente raccomandato, quindi hai bisogno di una serie di socket (mi piace anche sentire le tue opinioni su questo). Ora, il problema che si ottiene è, quel socket, instanzia i socket, quindi

s = socket.socket(family, type,..)

invece di

s = Socket()

quindi quello che volevo fare è

class ChatSocket(Socket)
  def getNickname()
    return "bob" # obviously an example for simplicity

s = ChatSocket() 

Prima domanda: Perché funziona in questo modo e non ha un'istanza "normale"?

Seconda domanda: Qual è secondo te una soluzione elegante a questa sfida?

Spero che abbia senso ... Qualsiasi pensiero è molto gradito

    
posta Erik Ros 01.10.2015 - 22:06
fonte

2 risposte

3
s = socket.socket(family, type,..)

in stead of

s = Socket()

Why does it work this way and doesn't it have a 'normal' instantiation?

Ma questa è una normale initalizzazione! socket è un modulo (o spazio dei nomi) e socket.socket è la classe socket nello spazio dei nomi socket , e socket.socket(family, type) richiama quel costruttore. Ciò potrebbe essere più chiaro se si importa quel modulo con un nome personalizzato:

import socket as socketmodule
# then:
s = socketmodule.socket(...)

Oppure potresti alias il nome della classe:

Socket = socket.socket
s = Socket(...)

In Python, i moduli e le classi sono valori ordinari che vengono passati in runtime, quindi possiamo usare variabili ordinarie per nominarli.

Puoi creare una sottoclasse del socket integrato per fornire un comportamento personalizzato. Ad esempio:

class ChatSocket(socket.SocketType):
  def __init__(self):
    super(socket.SocketType, self).__init__(family, type) # assuming Python 2.x
    other_initalization()

  def nickname(self):
    return "bob"

(I nomi socket.socket e socket.SocketType sono la stessa classe.)

Tuttavia, la sottoclasse di una classe su cui non hai alcun controllo e che non è intesa per la sottoclasse potrebbe non essere una buona idea. Piuttosto, inserisci il socket in una variabile membro e avvolgi tutti i metodi che vuoi esporre:

class ChatSocket(object):
  def __init__(self):
    self.socket = socket.socket()

  def nickname(self):
    return "bob"

  def accept(self):
    return self.socket.accept()

  ...

Ciò ti consente di controllare con maggiore precisione l'interfaccia che la tua classe offre.

    
risposta data 01.10.2015 - 22:31
fonte
0

Come qualcuno ha affermato che un file python è fondamentalmente un modulo quindi se si ha una classe chiamata Socket in un file socket.py e si usa l'istruzione import come

import socket 

devi fare riferimento alle chiamate Socket (per instanciation) come

s = socket.Socket()

Potresti anche usare l'istruzione from per importare una funzione o una classe speciale dal modulo come

from socket import Socket, ChatSocket 

Questa è la sintassi python 2.x se si utilizza python 3.x, potrebbe essere necessario essere più specifici con le referenze nelle istruzioni di importazione. E nel tuo esempio hai usato lezioni di vecchio stile che sono considerate di cattivo gusto. Dal 2.5 (se ricordo bene) dovresti ereditare la tua classe da oggetto come

class A(object):

in python tutto è fondamentalmente un oggetto.

    
risposta data 15.10.2015 - 13:18
fonte

Leggi altre domande sui tag