Zanurkuj w Pythonie/Metody specjalne: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
mNie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 1:
== 5.6.
In addition to normal class methods, there are a number of special methods that Python classes can define. Instead of being called directly by your code (like normal methods), special methods are called for you by Python in particular circumstances or when specific syntax is used.
Linia 10:
def __getitem__(self, key): return self.data[key]
>>> f = fileinfo.FileInfo("/music/_singles/kairo.mp3")▼
>>> f▼
{'name':'/music/_singles/kairo.mp3'}▼
>>> f.__getitem__("name") #(1)▼
'/music/_singles/kairo.mp3'▼
>>> f["name"] #(2)▼
'/music/_singles/kairo.mp3'▼
▲>>> f = fileinfo.FileInfo("/music/_singles/kairo.mp3")
▲>>> f
▲{'name':'/music/_singles/kairo.mp3'}
▲>>> f.__getitem__("name") 1
▲'/music/_singles/kairo.mp3'
▲>>> f["name"] 2
▲'/music/_singles/kairo.mp3'
▲1 The __getitem__ special method looks simple enough. Like the normal methods clear, keys, and values, it just redirects to the dictionary to return its value. But how does it get called? Well, you can call __getitem__ directly, but in practice you wouldn't actually do that; I'm just doing it here to show you how it works. The right way to use __getitem__ is to get Python to call it for you.
▲2 This looks just like the syntax you would use to get a dictionary value, and in fact it returns the value you would expect. But here's the missing link: under the covers, Python has converted this syntax to the method call f.__getitem__("name"). That's why __getitem__ is a special class method; not only can you call it yourself, you can get Python to call it for you by using the right syntax.
Of course, Python has a __setitem__ special method to go along with __getitem__, as shown in the next example.
Linia 26:
def __setitem__(self, key, item): self.data[key] = item
>>> f▼
{'name':'/music/_singles/kairo.mp3'}▼
>>> f.__setitem__("genre", 31) #(1)▼
>>> f▼
{'name':'/music/_singles/kairo.mp3', 'genre':31}▼
>>> f["genre"] = 32 #(2)▼
>>> f▼
{'name':'/music/_singles/kairo.mp3', 'genre':32}▼
▲>>> f
▲{'name':'/music/_singles/kairo.mp3'}
▲>>> f.__setitem__("genre", 31) 1
▲>>> f
▲{'name':'/music/_singles/kairo.mp3', 'genre':31}
▲>>> f["genre"] = 32 2
▲>>> f
▲{'name':'/music/_singles/kairo.mp3', 'genre':32}
▲1 Like the __getitem__ method, __setitem__ simply redirects to the real dictionary self.data to do its work. And like __getitem__, you wouldn't ordinarily call it directly like this; Python calls __setitem__ for you when you use the right syntax.
▲2 This looks like regular dictionary syntax, except of course that f is really a class that's trying very hard to masquerade as a dictionary, and __setitem__ is an essential part of that masquerade. This line of code actually calls f.__setitem__("genre", 32) under the covers.
__setitem__ is a special class method because it gets called for you, but it's still a class method. Just as easily as the __setitem__ method was defined in UserDict, you can redefine it in the descendant class to override the ancestor method. This allows you to define classes that act like dictionaries in some ways but define their own behavior above and beyond the built-in dictionary.
Linia 46:
Example 5.14. Overriding __setitem__ in MP3FileInfo
def __setitem__(self, key, item): #(1)
if key == "name" and item: #(2)
self.__parse(item) #(3)
FileInfo.__setitem__(self, key, item) #(4)
Note
When accessing data attributes within a class, you need to qualify the attribute name: self.attribute. When calling other methods within a class, you need to qualify the method name: self.method.
Example 5.15. Setting an MP3FileInfo's name
>>> import fileinfo
>>> mp3file = fileinfo.MP3FileInfo() #(1)
>>> mp3file
{'name':None}
>>> mp3file["name"] = "/music/_singles/kairo.mp3" #(2)
>>> mp3file
{'album': 'Rave Mix', 'artist': '***DJ MARY-JANE***', 'genre': 31,
'title': 'KAIRO****THE BEST GOA', 'name': '/music/_singles/kairo.mp3',
'year': '2000', 'comment': 'http://mp3.com/DJMARYJANE'}
>>> mp3file["name"] = "/music/_singles/sidewinder.mp3" #(3)
>>> mp3file
{'album': '', 'artist': 'The Cynic Project', 'genre': 18, 'title': 'Sidewinder',
'name': '/music/_singles/sidewinder.mp3', 'year': '2000',
'comment': 'http://mp3.com/cynicproject'}
<noinclude>
|