2010-04-24 20 views
14

Các phương pháp hay nhất để mở rộng mô-đun python - trong trường hợp này tôi muốn mở rộng python-twitter bằng cách thêm các phương thức mới vào lớp API cơ sở.Làm cách nào để mở rộng mô-đun python? (python-twitter)

Tôi đã xem xét kỹ lưỡng, và tôi cũng thích điều đó, tôi chỉ thấy python-twitter dễ hiểu hơn và mở rộng với chức năng tôi muốn.

Tôi có các phương pháp đã được viết, tôi chỉ cố gắng tìm ra cách tốt nhất để thêm chúng vào mô-đun, mà không thay đổi lõi.

+0

Bạn phải tự hỏi mình những gì nó là bạn cố gắng thực hiện điều đó không thể được giải quyết cho bạn bằng cách phân lớp chức năng từ mô-đun hiện có. – jathanism

+0

Chủ đề thú vị trên nhóm tin tức Python về những gì tôi ban đầu đã tìm kiếm đã dẫn tôi đến phần Hỏi & Đáp này, chủ đề từ giống như, 13 năm trở lại: https://mail.python.org/pipermail/python-dev/2002-June /024839.html –

Trả lời

17

Một vài cách.

Cách dễ dàng:

Đừng mở rộng các mô-đun, mở rộng các lớp học.

exttwitter.py

import twitter 

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

Nhược điểm: Mỗi lớp trong twitter phải exttwitter.py, ngay cả khi nó chỉ là một sơ khai (như trên)

Một khó khăn hơn (có thể un-pythonic) cách:

Nhập * từ python-twitter vào mô-đun mà bạn sau đó mở rộng.

Ví dụ:

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 

Tôi không chắc chắn nếu việc nhập khẩu tăng gấp đôi trong extmodule.py là python ic - bạn có thể loại bỏ nó, nhưng sau đó bạn không xử lý các usecase muốn mở rộng một chức năng trong không gian tên của basemodule.

Theo như các lớp mở rộng, chỉ cần tạo một lớp API (basemodule.API) mới để mở rộng mô-đun API Twitter.

+0

cảm ơn, tôi đã tìm kiếm một cái gì đó như thế để ghi đè lên json.dumps trên tất cả các dự án của tôi. (trong khi vẫn giữ các chức năng khác) – njzk2

+0

Tôi sẽ không xem xét việc này là unpythonic. Đó là thủ thuật hữu ích như thế này mà có thể làm cho việc sử dụng python rất mạnh mẽ. Chỉ cần rõ ràng về những gì bạn đang làm. Hãy thử làm điều đó trong Java hoặc C++ :-) – ThatAintWorking

6

Không thêm chúng vào mô-đun. Phân lớp các lớp bạn muốn mở rộng và sử dụng các lớp con của bạn trong mô-đun của riêng bạn, không thay đổi các nội dung gốc.

+0

Ok, tôi chưa quen với phân lớp trong python, (Tôi là kỹ sư, vẫn quen với phong cách OO), bạn có tài nguyên yêu thích không? Vì vậy, về cơ bản không có gì đặc biệt về một mô-đun ... Tôi chỉ có thể viết mô-đun mới sử dụng lớp python-twitter API làm lớp cơ sở và sau đó thêm vào các phương thức tôi muốn ..? – user319045

+0

@ user319045, Để phân lớp bạn chỉ cần viết mô-đun của riêng bạn tạo một lớp mới bằng cách sử dụng cú pháp 'class SomeName (othermodule.TheClassYouAreExtending): ...' và 'SomeName' sẽ phụ thuộc vào lớp gốc trong một well- cách xác định. Điều này được gọi là * kế thừa * và là cách bạn thường thêm các phương thức vào một lớp. Chủ đề này và các chủ đề khác được đề cập trong http://tinyurl.com/thinkcspy2e, đây là một cuốn sách giới thiệu cho bạn về Python và OOP. Nó có sẵn trực tuyến miễn phí và trong in ấn và là tốt hơn so với một số các tùy chọn khác tôi đã nhìn thấy. –

+0

Các hướng dẫn chính thức http://docs.python.org/tut/ cũng khá tốt, nhưng có thể chứng minh khó khăn hơn cho những người không phải là lập trình viên giàu kinh nghiệm với sự hiểu biết tốt về các mô hình lập trình mà họ đang sử dụng. –

1

Tôi có thể đề nghị không sáng tạo lại Bánh xe ở đây không? Tôi đang xây dựng một> 6k dòng Twitter Client cho 2 tháng nay, lúc đầu tôi đã kiểm tra python-twitter, nhưng nó tụt hậu so với những thay đổi gần đây của API, phát triển dường như không hoạt động, hoặc cũng có (ít nhất là khi tôi kiểm tra lần cuối) không có hỗ trợ cho OAuth/xAuth).

Vì vậy, sau khi tìm kiếm xung quanh một chút tôi càng khám phá ra tweepy:
http://github.com/joshthecoder/tweepy

Ưu điểm: phát triển tích cực, OAauth/Xauth và cập nhật với các API.
Rất có thể những gì bạn cần đã có trong đó.

Vì vậy, tôi đề nghị đi với điều đó, nó làm việc đối với tôi, điều duy nhất tôi đã phải thêm là Xauth (mà đã sáp nhập trở lại tweepy :)

Oh một một plug không biết xấu hổ, nếu bạn cần phải phân tích Tweets và/hoặc định dạng chúng sang HTML sử dụng phiên bản python của tôi về thư viện * twitter-giáo khoa:
http://github.com/BonsaiDen/twitter-text-python

điều này là unittestetd một đảm bảo để phân tích Tweets giống như Twitter.com hiện nó.

+0

Cảm ơn, tôi đã nhìn tweepy, tôi chỉ có vẻ như phong cách của python-twitter tốt hơn. Tôi không xây dựng một khách hàng twitter, chỉ là một bộ công cụ để xử lý một vài điều rất tốt liên quan đến nghiên cứu. – user319045

2

Giả sử bạn có một module cũ gọi mod mà bạn sử dụng như thế này:

import mod 

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

Và bạn muốn mở rộng nó, mà không cần thay thế nó cho người dùng của bạn. Dễ dàng thực hiện. Bạn có thể đặt cho mô-đun mới của mình một tên khác, newmod.py hoặc đặt tên mô-đun đó theo cùng một đường dẫn sâu hơn và giữ cùng tên, ví dụ: /path/to/mod.py. Sau đó, người dùng của bạn có thể nhập nó bằng một trong các cách sau:

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

hoặc

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

Trong mô-đun của bạn, bạn sẽ muốn làm cho tất cả các tên tuổi sẵn:

from mod import * 

hoặc đặt tên rõ ràng cho mỗi tên bạn nhập:

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 

Tôi nghĩ rằng import * sẽ dễ bảo trì hơn cho trường hợp sử dụng này - nếu mô-đun cơ sở mở rộng chức năng, bạn sẽ liên tục theo kịp (mặc dù bạn có thể tô sáng các đối tượng mới có cùng tên).

Nếu mod bạn đang mở rộng có phong nha __all__, nó sẽ hạn chế các tên được nhập.

Bạn cũng nên khai báo một số __all__ và mở rộng nó bằng mô-đun mở rộng __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) 

Sau đó, mở rộng đối tượng và chức năng như bình thường.

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

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

Nếu các đối tượng mới cung cấp chức năng bạn có ý định thay thế (hoặc có lẽ bạn đang backporting các chức năng mới vào một cơ sở mã cũ), bạn có thể ghi đè lên tên

Các vấn đề liên quan