Python Forum

Full Version: Pass an object to a class, then make an object of it and pass again
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
"anti-pattern" translates to "You are doing it wrong".

Everything in Python is open to the public. There is no concept of "private" like there is in C++ and most other OOP languages. Because all things are public and because Python programmers are lazy, the common practice (pattern) is to directly reference instance variables using namespace.variable_name. This is generally a good thing because it results in less code to write and maintain and reduces the amount of code someone has to learn to use you class. It would be very common for somebody using your class to directly reference eyes as spider.Body.top.eyes=8 instead of using the spider.set_eyes(8) method. This is so common that most class authors only write a "setter" if setting a class attribute has some side effect.

For example, let's say you have a set_feet() method that also sets the number of legs.
def set_feet(self, num_feet, num_legs=None):
    self.feet = num_feet
    self.legs = num_feet if num_legs is None else num_legs
This makes it easier for the class user without adding much code and it enforces consistency between legs and feet. Another reason for writing setters is they provide a handle for connecting your classes to GUI controls and timers and things that need a function.
I had no intention to go into details about properties/setters, but maybe it's worth a bit of explaining

Let's say we have class Person. It has two attributes which we pass when instantiate it

class Person:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

person = Person('John', 'Doe')
print(person.first_name)
print(person.last_name)
What if we want a third attribute name that is the full name, i.e. <first_name> <last_name> - John Doe.
We can add a third attribute, just the same like the other two. However to have consistency we can do

class Person:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @property
    def name(self):
        return f'{self.first_name} {self.last_name}'

person = Person('John', 'Doe')
print(person.first_name)
print(person.last_name)
print(person.name)
person.name = 'Jack Ryan'


If you run the snippet you can see we are not able to change name (it raise error). To be able to change it, we can define setter for name. Again, for consistency we need to change also first_name and/or last_name when we change name, e.g.


class Person:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @property
    def name(self):
        return f'{self.first_name} {self.last_name}'

    @name.setter
    def name(self, value):
        self.first_name, *_, self.last_name = value.split(' ')

person = Person('John', 'Doe')
print(person.first_name)
print(person.last_name)
print(person.name)
person.name = 'Jack Ryan'
print(person.first_name)
print(person.last_name)
print(person.name)
Output:
John Doe John Doe Jack Ryan Jack Ryan
This is just a basic example, in other cases you may need to use "private" variable, that is considered "for internal use" and it is designated by single underscore, e.g. _some_name. This is not really private variable like in other languages, just by convention "for internal use".
Pages: 1 2