[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