How do you create methods of type dot notation, those that are called object.show ()
instead of show ( objec )
, or do they apply only to strings, if so why exactly?
How do you create methods of type dot notation, those that are called object.show ()
instead of show ( objec )
, or do they apply only to strings, if so why exactly?
Point notation in Python is used to retrieve attributes of objects. In particular in Python, there is no distinction at the moment you use the dot between an "attribute" and a "method" - as in Python everything is an object and what distinguishes the methods is that they are "callable" members ( "callable") of an object.
So to create a method, the most common way is to create a class, and define the methods inside the body of the class with the def <nome>
(self, [parametro, ...]):
notation - just like we do with loose functions. After that, when creating instances of this class, the methods will be available:
class A:
def b(self):
print(f"Método b chamado no objeto {self}")
a = A()
a.b()
If you paste iso in the interactive mode (Python 3.6) the output will look something like:
Método b chamado no objeto <__main__.A object at 0x7f19d24b77b8>
(For versions of Python between 3.0 and 3.5, remove the "f-string" and use the ".format" method.)
There are other ways of putting recoverable attributes by point - for example simple assignment - that can be done as much in the class as in some object instance. Continuing the example above:
def bla():
print("bla chamado")
a.bla = bla
a.bla()
This time the "a" function becomes an attribute of the a
instance of the A
class object we created. The biggest difference being that this way it does not automatically get a reference to the instance itself (see, the bla
function was defined without the self
parameter and would give an error if it was coaxed with self
and used in that way).
The rules that Python uses to access an instance or class tribute - and when it automatically adds the self
attribute or not - are well-defined in the language. - but they require a certain study to be understood in their entirety, why they cover all the corner cases . For day-to-day use they are often intuitive enough. The Data Model might be the best document to understand the language as a whole and these rules.
A simplified summary just to understand the most basic attribute search - after the point there is an attribute name, and the Python runtime fetches the attribute on the object following these steps:
__getattribute__
method of the object is called with the parameters self
and the name of the attribute. As a rule, classes defined in "day to day" code do not redefine the __getattribute__
method - then this method is at the base of the Python object hierarchy - and searches the attribute. The next steps actually occur within of this __getattribute__
pattern. The first of the cases below that "match" is returned as the attribute: __get__
E one of __set__
or __del__
) - I will not detail what happens if he finds to keep this response at an intermediate level. All in all, when we use the decorator @property
it falls in this case. __dict__
attribute of the instance itself if there is a key with that name. S .__mro__
attribute of the class. __getattr__
method (it is unlike the __getattribute__
) of the class, baking the attribute name. __getattr__
fails, a AttributeError
exception occurs and the attribute is not retrieved. Furthermore, it is worth adding that for objects whose classes are defined directly in C, using the Python API, and not in pure Python, it is not usually possible to add new attributes or methods dynamically. That is, you can not hang new methods on the str
or int
classes of Python, as you can in Ruby.
Let's start with an example where 4 methods are created, being init
, the first two with the show (obj) notation and the last one with the call that you call 'dot notation. p>
View the code displayed in this response by running on repl.it.
class collection1::
def __init__(self):
self.lst = [1,2,3,4,5]
# Tamanho da collection (função len)
def __len__(self):
return len(self.lst)
# Fornece a posição de um item na collection
def __getitem__(self, position):
return self.lst[position]
# Apresenta a collection
def show(self):
print (self.lst)
Now let's instantiate and execute the methods:
c = collection1()
print (len(c))
5
print (c[3])
4
c.show()
[1, 2, 3, 4, 5]
Named and terminated methods with __
(dunderscore)
These are the special methods, called by some of the "magic methods," the main thing you should know about these methods is that you should not call them directly (although this can be done). Instead of using obj.__len__()
or obj.__getitem__[3]
you must use len(obj)
and obj[3]
. Note that if obj is a built-in type, such as list, str, etc. The interpreter will call a function (which may be in cpython) through a shortcut. If the class of which obj is an instance, it has been implemented by you, the interpreter will call the instance method that you have implemented, in __getitem__
and / or __len__
.
Why len is not a method?
Luciano Ramalho in his book Python Fluent , says he asked this question to one of the core developers in 2013 and the key to the response was a quote from The Zen of Python 'praticality beats purity' (The practicality surpasses purity). I recommend the book (no, I'm not earning anything. :-)) for more details.
Implementing our own str
in our class:
Let's suppose we needed or wanted to implement a "stuck" str in our class, we would just have to implement __str__
, like this:
def __str__(self):
return 'Classe especial com uma lista simples'
Now we could use the function str
as if it were a function built into python, the difference is that the interpreter will call our function:
obj = collection1()
print (obj)
Classe especial com uma lista simples
Conclusion
Except for the implementations of scape methods , most of the methods you develop will be of the type which you call "point notation", in fact, even the special methods have the same implementation (that of those notation) the difference is only in the call and the magic.