2010-04-24 11 views
14

Quali sono le migliori pratiche per estendere un modulo python - in questo caso voglio estendere python-twitter aggiungendo nuovi metodi alla classe API di base.Come estendere un modulo Python? (python-twitter)

Ho guardato il tweepy, e mi piace anche questo, ho trovato python-twitter più facile da capire ed esteso con la funzionalità che voglio.

Ho già scritto i metodi, sto solo cercando di capire il modo migliore per aggiungerli al modulo, senza modificare il core.

+0

Bisogna chiedersi che cosa è sei cercando di ottenere risultati che non possono essere risolti per te sottoclassi la funzionalità dal modulo esistente. – jathanism

+0

Interessante discussione sul gruppo di notizie su Python su ciò che cercavo in origine mi ha portato a questo Q & A, il thread è simile a 13 anni fa: https://mail.python.org/pipermail/python-dev/2002-June /024839.html –

risposta

17

Alcuni modi.

Il modo più semplice:

Non estendere il modulo, si estendono le classi.

exttwitter.py

import twitter 

class Api(twitter.Api): 
    pass 
    # override/add any functions here. 

Downside: Ogni classe twitter deve essere exttwitter.py, anche se è solo uno stub (come sopra)

una più dura (possibilmente non-divinatorio) way:

Importa * da python-twitter in un modulo da estendere.

Per esempio:

basemodule.py

class Ball(): 
    def __init__(self,a): 
     self.a=a 
    def __repr__(self): 
     return "Ball(%s)" % self.a 

def makeBall(a): 
    return Ball(a) 

def override(): 
    print "OVERRIDE ONE" 

def dontoverride(): 
    print "THIS WILL BE PRESERVED" 

extmodule.py

from basemodule import * 
import basemodule 

def makeBalls(a,b): 
    foo = makeBall(a) 
    bar = makeBall(b) 
    print foo,bar 

def override(): 
    print "OVERRIDE TWO" 

def dontoverride(): 
    basemodule.dontoverride() 
    print "THIS WAS PRESERVED" 

runscript.py

import extmodule 

#code is in extended module 
print extmodule.makeBalls(1,2) 
#returns Ball(1) Ball(2) 

#code is in base module 
print extmodule.makeBall(1) 
#returns Ball(1) 

#function from extended module overwrites base module 
extmodule.override() 
#returns OVERRIDE TWO 

#function from extended module calls base module first 
extmodule.dontoverride() 
#returns THIS WILL BE PRESERVED\nTHIS WAS PRESERVED 

Non sono sicuro se il doppio di importazione in extmodule.py è python ic - potresti rimuoverlo, ma in questo caso non gestirai l'usecase di voler estendere una funzione che si trovava nello spazio dei nomi di basemodule.

Per quanto riguarda le classi estese, è sufficiente creare una nuova classe API (basemodule.API) per estendere il modulo API di Twitter.

+0

grazie, stavo cercando qualcosa del genere per sovrascrivere json.dump su tutto il mio progetto. (mantenendo le altre funzioni) – njzk2

+0

Non lo considererei unpythonic. Sono trucchi utili come questo che possono rendere l'uso di Python così potente. Basta essere chiari su quello che stai facendo. Prova a farlo in Java o C++ :-) – ThatAintWorking

6

Non aggiungerli al modulo. Sottoclassi le classi che vuoi estendere e usa le sottoclassi nel tuo modulo, non cambiando affatto le cose originali.

+0

Ok, non ho ancora familiarità con la sottoclassificazione in Python, (sono un ingegnere, mi sto ancora abituando allo stile OO), hai una risorsa preferita? Quindi, in fondo non c'è nulla di speciale in un modulo ... posso solo scrivere un nuovo modulo che utilizza API di classe python-twitter come classe base e quindi aggiungere nei metodi che voglio ..? – user319045

+0

@ user319045, Per sottoclasse devi semplicemente scrivere il tuo modulo che crea una nuova classe usando la classe 'di sintassi SomeName (othermodule.TheClassYouAreExtending): ...' e 'SomeName' dipenderanno dalla classe originale in un pozzo modo definito. Questo è chiamato * ereditarietà * ed è il modo in cui normalmente si aggiungono metodi a una classe. Questo e altri argomenti sono trattati in http://tinyurl.com/thinkcspy2e, che è un libro che ti introdurrà a Python e OOP. È disponibile gratuitamente online e in stampa ed è migliore di alcune delle altre opzioni che ho visto. –

+0

Il tutorial ufficiale http://docs.python.org/tut/ è anche abbastanza buono, ma potrebbe rivelarsi più difficile per le persone che non sono programmatori esperti con una buona conoscenza dei paradigmi di programmazione che stanno utilizzando. –

1

Posso suggerire di non reinventare la ruota qui? Sto costruendo un client Twitter> 6k line per 2 mesi, inizialmente ho controllato anche python-twitter, ma è molto indietro rispetto alle recenti modifiche API, anche lo sviluppo non sembra essere così attivo (almeno quando ho controllato l'ultima volta) nessun supporto per OAuth/xAuth).

Così, dopo aver cercato in giro un po 'più ho scoperto tweepy:
http://github.com/joshthecoder/tweepy

Pro: lo sviluppo attivo, OAauth/xauth e al passo con l'API.
Le probabilità sono alte che quello che ti serve è già lì dentro.

Quindi suggerisco di andare con questo, si sta lavorando per me, l'unica cosa che ho dovuto aggiungere era XAuth (che ha ottenuto fondersi di nuovo a tweepy :)

Oh un una spina spudorato, se è necessario analizzare Tweets e/o formattare in HTML usare la mia versione di Python delle librerie twitter-testo- *:
http://github.com/BonsaiDen/twitter-text-python

Questa cosa è unittestetd una garanzia per analizzare Tweets proprio come Twitter.com fa.

+0

Grazie, ho guardato tweepy, mi sembra che mi piaccia lo stile di python-twitter. Non sto costruendo un client twitter, solo una suite di strumenti per gestire alcune cose molto bene per quanto riguarda la ricerca. – user319045

2

Diciamo che avete un modulo più vecchio chiamato mod che si utilizza in questo modo:

import mod 

obj = mod.Object() 
obj.method() 
mod.function() 
# and so on... 

e si vuole estendere, senza sostituirla per gli utenti. Facilmente fatto. Puoi dare al tuo nuovo modulo un nome diverso, newmod.py o posizionarlo con lo stesso nome in un percorso più profondo e mantenere lo stesso nome, ad es. /path/to/mod.py. Quindi gli utenti possono importare in uno dei seguenti modi:

import newmod as mod  # e.g. import unittest2 as unittest idiom from Python 2.6 

o

from path.to import mod # useful in a large code-base 

Nel modulo, ti consigliamo di fare tutti i vecchi nomi disponibili:

from mod import * 

o denominare esplicitamente ogni nome che si importa:

from mod import Object, function, name2, name3, name4, name5, name6, name7, name8, name9, name10, name11, name12, name13, name14, name15, name16, name17, name18, name19, name20, name21, name22, name23, name24, name25, name26, name27, name28, name29, name30, name31, name32, name33, name34, name35, name36, name37, name38, name39 

Penso che lo import * sarà più manutenibile per questo caso d'uso - se il modulo base espande la funzionalità, continuerai senza problemi (anche se potresti ombreggiare nuovi oggetti con lo stesso nome).

Se il mod si sta estendendo ha un __all__ decente, limiterà i nomi importati.

È inoltre necessario dichiarare un __all__ ed estenderlo con il modulo esteso __all__.

import mod 
__all__ = ['NewObject', 'newfunction'] 
__all__ += mod.__all__ 
# if it doesn't have an __all__, maybe it's not good enough to extend 
# but it could be relying on the convention of import * not importing 
# names prefixed with underscores, (_like _this) 

quindi estendere gli oggetti e le funzionalità come si farebbe normalmente.

class NewObject(object): 
    def newmethod(self): 
     """this method extends Object""" 

def newfunction(): 
    """this function builds on mod's functionality""" 

Se i nuovi oggetti forniscono funzionalità che si intende sostituire (o forse si sta backport la nuova funzionalità in una base di codice più vecchio) è possibile sovrascrivere i nomi