2012-07-23 12 views
5

Lubię robić głupie rzeczy z pytonem jak rozwiązywanie zagadek programistycznych, pisanie małych skryptów itp. Za każdym razem w pewnym momencie stoję przed dylematem, czy powinienem stworzyć nową klasę do reprezentowania moich danych lub po prostu użyć szybkiego i brudnego i przejdź do wszystkich wartości spakowanych na liście lub krotce. Z powodu skrajnego lenistwa i osobistej niechęci do słowa kluczowego Izwykle używam drugiej opcji.Jak zdecydować, kiedy wprowadzić nowy typ zamiast listy lub krotki?

Rozumiem niż w instrukcji dłuższą metę określonym typem danych jest lepiej, bo path.min_cost i point.x, point.y jest znacznie bardziej wyraziste niż path[2] i point[0], point[1]. Ale kiedy po prostu potrzebuję zwrócić wiele rzeczy z funkcji, uderza mnie to za dużo pracy.

Moje pytanie brzmi: jaka jest dobra zasada, aby wybrać, kiedy należy utworzyć typ danych zdefiniowany przez użytkownika i kiedy należy wybrać listę lub krotkę? A może jest jakiś zgrabny, pytonowy sposób, o którym nie wiem?

Dzięki.

+4

'self' faktycznie jest _nie_ słowem kluczowym, ale zwykłą nazwą zmiennej. Zdecydowanie sugeruję, abyś się w nim trzymał, ale w praktyce możesz użyć np. '_' zamiast' self'. – Kimvais

+0

Myślę, że jeśli użyjesz programu dwa lub więcej razy, lepiej zapisz go na zajęciach. – aasa

Odpowiedz

2

Po pierwsze, obserwacja na temat ekspresji. Wspomniałeś, że martwisz się względną ekspresyjnością point.x, point.y vs. point[0], point[1], ale jest to problem, który można rozwiązać na więcej niż jeden sposób. W rzeczywistości, dla prostego point struktury, myślę, że jest to argument, aby przyjąć, że klasa jest przesadą, zwłaszcza gdy można po prostu to zrobić:

x, y = get_point(foo) 

chciałbym powiedzieć, że to właśnie o tak wyraziste jak point.x, point.y; Prawdopodobnie będzie też szybszy (niż w przypadku klasy vanilla - nie ma żadnych porównań) i jest całkiem czytelny, zakładając, że krotka zawiera tylko kilka elementów.

Moje podejście do decydowania, czy umieścić coś w klasie, ma więcej wspólnego z tym, w jaki sposób wykorzystam dane w całym programie: zadaję sobie pytanie "czy to jest stan?" Jeśli mam pewne dane, które znam, bardzo się zmienią i muszą być przechowywane w jednym miejscu i zmanipulowane przez grupę specjalnie zaprojektowanych funkcji, to wiem, że dane to prawdopodobnie stan, i powinienem przynajmniej rozważyć umieszczenie go w Klasa. Z drugiej strony, jeśli mam dane, które się nie zmienią lub są efemeryczne i powinny zniknąć, gdy skończę, prawdopodobnie nie jest to stan i prawdopodobnie nie trzeba wchodzić do klasy.

Jest to, oczywiście, tylko zasada; na przykład, mogę wymyślić przypadki, w których może być potrzebny rodzaj "rekordu", aby można było manipulować dość złożoną kolekcją danych bez posiadania 15 różnych zmiennych lokalnych (stąd istnienie namdetuple). Ale często, jeśli manipulujesz tylko jednym lub dwoma z nich, lepiej będzie utworzyć funkcję, która akceptuje jedną lub dwie wartości i zwraca jedną lub dwie wartości, a do tego krotka lub lista jest idealnie w porządku.

2

Jest to z pewnością subiektywne, ale staram się przestrzegać zasady najmniejszego zaskoczenia.

Jeśli zwrócone wartości opisują charakterystykę obiektu (np. point.x i point.y w twoim przykładzie), wówczas użyłbym klasy.

Jeśli nie są częścią tego samego obiektu (powiedzmy: return min, max), to powinny być krotką.

8

Czy znasz numer collections.namedtuple? (since 2.6)

def getLocation(stuff): 
    return collections.namedtuple('Point', 'x, y')(x, y) 

lub bardziej skutecznie,

Point = collections.namedtuple('Point', 'x, y') 
def getLocation(stuff): 
    return Point(x, y) 

namedtuple mogą być dostępne przez indeks (point[0]) i rozpakowaniu (x, y = point) taki sam sposób jak tuple, więc oferuje prawie bezbolesne ścieżkę uaktualnienia .

+0

Możesz również dziedziczyć po 'namedtuple' jak w' class Foo (namedtuple ("BaseFoo", "ham spam"))), co oszczędza pisanie jakiejś płytki konstruktora. –

Powiązane problemy