[TasPython] decorators + Lots of __init__ args
Apostolos Bessas
mpessas at gmail.com
Mon Dec 20 19:40:48 CET 2010
Το check_if_ready τώρα που το βλέπω μπορεί να γραφτεί ως decorator (με
κατάλληλο modification), για να χρησιμοποιηθεί από όλες τις
συναρτήσεις (code reuse baby!).
Αποστόλης
2010/12/20 Apostolos Bessas <mpessas at gmail.com>:
> Υπάρχει και η εξής σχετική ιδέα (που χρησιμοποιείται μεταξύ άλλων και
> από τη Qt, αν θυμάμαι καλά):
> Τα αντικείμενα που δημιουργεί ο contructor (initializer actually στη
> python) δεν είναι "ready". Οι παράμετροι περνιούνται μέσω
> getters/setters των ιδιοτήτων των αντικειμένων. Μόνο όταν όλες οι
> απαραίτητες παράμετροι οριστούν (ανατεθεί κάποια τιμή σε αυτές) το
> αντικείμενο μαρκάρεται ως ready και μπορεί να χρησιμοποιηθεί (πχ
> save() to db).
>
> Κάπως έτσι (disclaimer: code not tested, not even for correct syntax /
> could use cleanup):
>
> class User(object):
> def __init__(self):
> self.__ready = False
> self.__args = (name, username, password, )
>
> def name(self):
> return self.__name
>
> def set_name(self, name):
> self.__name = name
>
> def __check_if_ready(self):
> if all(self.__args):
> self.__ready = True
>
> def save(self):
> if not self.__ready:
> self.__check_if_ready()
> if not self.__ready:
> raise NotReadyError("Not ready yet")
> self.__save()
>
> Αν θυμάμαι καλά, πρέπει να έχω δει το παραπάνω και σε guide της
> Trolltech (Nokia πλέον) για API design. Σαν στυλ, το προτιμώ από το να
> περνάς dicts δεξιά και αριστερά (όχι ότι οι δύο προσεγγίσεις είναι
> ισοδύναμες (η δεύτερη δουλεύει σε C++ που είναι γραμμένη η Qt, ενώ η
> πρώτη όχι, αλλά η πρώτη βολεύει σε άλλες περιπτώσεις)).
>
> Αποστόλης
>
> PS http://stackoverflow.com/questions/895296/how-can-you-tell-if-a-person-is-a-programmer/895359#895359
>
> 2010/12/20 Themistoklis Savvidis <themhs at gmail.com>:
>> Χαίρετε,
>>
>> στα πλαίσια της τελευταίας συνάντησης σχετικά με τους decorators, σκέφτηκα
>> να
>> μοιραστώ με τη λίστα μια λύση που μου πρότεινε ο Δημήτρης (Γλέζος) στο
>> παρακάτω
>> θέμα:
>>
>> Ε: Έστω πως έχω μια κλάση User. Κάθε αντικείμενο της User θέλω να μπορει να
>> αρχικοποιεί 20 μεταβλητές (username, name, surname, age, email, phone_num
>> και
>> ό,τι άλλο μπορείτε να φανταστείτε) όταν αυτό δημιουργείται. Πώς λοιπόν θα
>> το
>> πετύχω αυτό;
>>
>> α) Θα έχει ο constructor της User 20 όρισματα με τα οποία θα αρχικoποιώ
>> μία-μία τις μεταβλητές αντικειμένου; (hint: είμαι σίγουρος πως τα
>> μαλλιά
>> κάποιοων έχουν σηκωθεί ανεπανόρθωτα στο ανάγνωσμα της (a) πρότασης)
>>
>> β) Θα βάλω σαν όρισμα **kwargs και θα κάνω κάποια 'χακιά';
>> Σα 'χακιά' εδώ εννούσα να παίξω απευθείας με το self.__dict__, τεχνική
>> που δεν ξέρω αν είναι γενικώς αποδεκτή και προτεινόμενη:
>>
>> def __init__(self, **kwargs):
>> for (key, item) in kwargs.items():
>> self.__dict__[key] = item
>>
>> γ) Υπάρχει κάποιος πιο όμορφος τρόπος;
>>
>> A: O Δημήτρης μου πρότεινε σε πρώτη φάση να χρησιμοποιήσω την update() των
>> λεξικών, της οποίας την ύπαρξη αγνοούσα:
>>
>> def __init__(self, **kwargs):
>> self.__dict__.update(kwargs)
>>
>> Αυτό όμως, όπως μου εξήγησε, είναι κάπως περίεργο γιατί ένας Theoς ξέρει
>> μόνο
>> τι θα του περάσουμε σαν kwargs - αν κ ακόμη κ αυτό τις τελευταίες 2
>> βδομάδες
>> αμφίσβητείται. So, μια πιο restricted λύση είναι η εξής:
>>
>> class User:
>>
>> init_properties = ['username', 'name', 'surname']
>>
>> @autoargs(init_properties)
>> def __init__(self, **kwargs):
>> self.__dict_.update(kwargs)
>>
>> όπου η init_properties είναι αυτή που καθορίζει ποια kwargs θα περαστούν
>> σαν
>> instance variables και ο decorator autoargs είναι αυτός που κάνει τη
>> βρώμικη
>> δουλειά, 'κόβοντας' όλα τα 'περίεργα' args.
>>
>> Μου άρεσε η ιδέα του, άνοιξα τον αγαπημένο editor του Κεραμίδα, πάτησα
>> 'i'
>> (sic) και έγραψα τον παρακάτω decorator:
>>
>> def autoargs(arg_list):
>> def decorator(func):
>> def wrapper(self, **kwargs):
>> [setattr(self,k,v) for (k,v) in kwargs.items() if k in
>> arg_list]
>> func(self, **kwargs)
>> return wrapper
>> return decorator
>>
>> ώστε πλέον o constructor γίνεται:
>>
>> @autoargs(init_properties)
>> def __init__(self, **kwargs):
>> pass
>>
>> Παρ' ολ' αυτά, επειδή αρχικά την ερώτηση έκανα στο Γιάννη (Καλαντζή),
>> έδωσα κ σ' αυτόν την απάντηση του Δημήτρη. Μου απαντάει "nice, για να
>> δούμε
>> πως το κάνει το django". Όπως αποδείχθηκε, και το το django χρησιμποιεί
>> την ίδια
>> λογική αλλά χωρίς τη χρήση decorators.
>>
>> Μία πιο προχωρημένη λύση με decorators που βρήκε ο Γιάννης για το ίδιο
>> πρόβλημα,
>> μπορείτε να δείτε εδώ:
>>
>>
>> http://stackoverflow.com/questions/1389180/python-automatically-initialize-instance-variables
>>
>> --
>> Themis
>>
>> _______________________________________________
>> TasPython mailing list
>> http://taspython.eu/
>> http://mail.python.org/mailman/listinfo/taspython
>>
>>
>
More information about the TasPython
mailing list