2010-04-24 16 views
14

Jakie są najlepsze praktyki dotyczące rozbudowy modułu Pythona - w tym przypadku chcę rozszerzyć python-twitter przez dodanie nowych metod do podstawowej klasy API.Jak przedłużyć moduł python? (python-twitter)

Spojrzałem na tweepy, a ja też to lubię, po prostu uważam, że python-twitter jest łatwiejszy do zrozumienia i poszerzenia o pożądaną funkcjonalność.

Mam już napisane metody, staram się wymyślić najlepszy sposób dodania ich do modułu, bez zmiany rdzenia.

+0

Trzeba zadać sobie pytanie, co to jest to próba osiągnięcia tego nie może zostać rozwiązana za pomocą podklasy funkcjonalności z istniejącego modułu. – jathanism

+0

Interesujący wątek w grupie dyskusyjnej Pythona na temat tego, czego początkowo szukałem, doprowadził mnie do tego pytania i odpowiedzi, wątek pochodzi z 13 lat temu: https://mail.python.org/pipermail/python-dev/2002-June /024839.html –

Odpowiedz

17

Kilka sposobów.

Prosty sposób:

Nie przedłużyć moduł przedłużyć klas.

exttwitter.py

import twitter 

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

Wada: Każda klasa w Twitterze musi być exttwitter.py, nawet jeśli to tylko zalążek (jak wyżej)

trudniejsze (ewentualnie un-pythonic) sposób:

Importuj * z Pythona-twittera do modułu, który następnie rozszerzasz.

Na przykład:

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 

Nie jestem pewien, czy podwójne import w extmodule.py jest python ic - możesz go usunąć, ale nie radzisz sobie z przypadkiem, gdy chcesz rozszerzyć funkcję, która była w przestrzeni nazw modułu bazowego.

W przypadku klas rozszerzonych wystarczy utworzyć nową klasę API (basemodule.API), aby rozszerzyć moduł interfejsu Twitter API.

+0

dziękuję, szukałem czegoś takiego, aby przesłonić json.dumps nad całym moim projektem. (zachowując pozostałe funkcje) – njzk2

+0

Nie uważam tego za niepython. To użyteczne sztuczki, które mogą sprawić, że używanie Pythona będzie tak potężne. Po prostu bądź oczywisty, co robisz. Spróbuj to zrobić w Javie lub C++ :-) – ThatAintWorking

6

Nie dodawaj ich do modułu. Podklasuj klasy, które chcesz rozszerzyć i użyj swoich podklas we własnym module, nie zmieniając w ogóle oryginalnego materiału.

+0

Ok, nie jestem jeszcze zaznajomiony z podklasą w pythonie, (jestem inżynierem, wciąż przyzwyczajam się do stylu OO), czy masz ulubione zasoby? W zasadzie nie ma nic szczególnego w module ... Mogę po prostu napisać nowy moduł, który wykorzystuje klasę API python-twitter jako klasę bazową, a następnie dodać metody, które chcę ..? – user319045

+0

@ user319045, Do podklasy należy napisać własny moduł, który tworzy nową klasę przy użyciu składni 'class SomeName (othermodule.TheClassYouAreExtending): ...' i 'SomeName' będzie zależał od oryginalnej klasy w dobrze określony sposób. Nazywa się to * dziedziczeniem * i jest tak, jak normalnie dodajesz metody do klasy. Ten i inne tematy są opisane w http://tinyurl.com/thinkcspy2e, która jest książką, która wprowadzi Cię w Python i OOP. Jest dostępny bezpłatnie online i drukowany i jest lepszy niż niektóre inne opcje, które widziałem. –

+0

Oficjalny tutorial http://docs.python.org/tut/ jest również całkiem niezły, ale może okazać się trudniejszy dla osób, które nie są doświadczonymi programistami dobrze rozumiejącymi paradygmaty programowania, z których korzystają. –

1

Czy mogę zasugerować, aby nie wymyślać tutaj koła? Buduję klienta Twittera> 6k przez 2 miesiące, najpierw sprawdziłem też python-twitter, ale opóźnia się on dużo za niedawnymi zmianami API. Rozwój nie wydaje się być tak aktywny, również było (przynajmniej kiedy ostatnio sprawdzałem) brak obsługi OAuth/xAuth).

Więc po wyszukaniu się trochę bardziej odkryłem tweepy:
http://github.com/joshthecoder/tweepy

Plusy: aktywny rozwój, OAauth/XAUTH i na bieżąco z API.
Szanse są wysokie, że to, czego potrzebujesz, już tam jest.

Więc proponuję jechać z tym, że to działa na mnie, jedyne co musiałem dodać był XAUTH (który dostał scalić z powrotem do tweepy :)

Oh jest bezwstydna, jeśli trzeba analizować tweetów i/lub formatować je do HTML używać wersji Pythona z Twittera na tekście * bibliotek:
http://github.com/BonsaiDen/twitter-text-python

ta rzecz unittestetd gwarancją analizowania tweetów jak Twitter.com to robi.

+0

Dzięki, spojrzałem na tweepy, wydaje mi się, że bardziej podoba mi się styl python-twitter. Nie buduję klienta Twittera, tylko zestaw narzędzi do radzenia sobie z kilkoma rzeczami bardzo dobrze w odniesieniu do badań. – user319045

2

Say masz starszą moduł o nazwie mod że używasz tak:

import mod 

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

I chcesz go przedłużyć, nie zastępując go dla użytkowników. Łatwo zrobić. Możesz nadać nowemu modułowi inną nazwę, newmod.py lub umieścić go o tej samej nazwie na głębszej ścieżce i zachować tę samą nazwę, np. /path/to/mod.py. Następnie użytkownicy mogą importować go w jeden z następujących sposobów:

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

lub

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

w module, będziemy chcieli, aby wszystkie stare nazwy dostępnych:

from mod import * 

lub jawnie nazwij każdą importowaną nazwę:

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 

Myślę, że import * będzie łatwiejszy w utrzymaniu w tym przypadku - jeśli moduł podstawowy rozszerzy funkcjonalność, będziesz płynnie nadążać (choć możesz odcień nowych obiektów o tej samej nazwie).

Jeśli rozszerzany mod ma przyzwoitą wartość __all__, ograniczy importowane nazwy.

Należy również zadeklarować numer __all__ i rozszerzyć go rozszerzonym modułem o numer __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) 

Następnie rozszerzaj obiekty i funkcjonalność w normalny sposób.

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

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

Jeśli nowe obiekty zapewniają funkcjonalność zamierzają zastąpić (lub być może jesteś backport nową funkcjonalność do starszego kodu bazowego) można zastąpić nazwy