#๐Ÿ”’ I think it's not a typo

82 messages ยท Page 1 of 1 (latest)

echo cove
#

as code is working fine but idk why he wrote that

craggy cairnBOT
#

@echo cove

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

fossil plinth
#

i don't see what's wrong?

deft galleon
echo cove
#

he create a public attribute in the init method but uses private attribute in the getter\

#

that is an older way

deft galleon
#

but he did set name = property(...)

fossil plinth
#

ah

deft galleon
#

so when calling Person.name it would run the getter function

fossil plinth
#

i wouldn't really recommended doing it this way

deft galleon
#

same

fossil plinth
#

much clearer to use the decorator

deft galleon
#

it is a decorator... just completely laid out

echo cove
deft galleon
deft galleon
echo cove
#

what if i use decorators...then?

deft galleon
echo cove
#

but in previous code he uses private attr in the init

deft galleon
#

you could do it both ways but that would be complicating yourself

echo cove
#

wait let me show you

fossil plinth
#

it is common to use a private attr

deft galleon
#

One thing to understand is there is no such thing as "private" btw. You can still access the _ attributes without the @property

echo cove
#

yeah

deft galleon
#

!e

class Person:
  def __init__(self, name):
    self._name = name

p = Person("ajay")
print(p._name)
craggy cairnBOT
deft galleon
echo cove
#

nothing, it is working...
but in this the private attr is also in the__init__

#

ok you wrote it

deft galleon
echo cove
#

wait is it being called directly

deft galleon
#

I will show a series of codes that will throw errors and I will do my best to explain it

echo cove
#

ty

deft galleon
#

!e

class Person:
  def __init__(self, name):
    self.name = name # This will cause an AttributeError
  @property
  def name(self):
    return self.name

p = Person("satyam")
print(p.name)
craggy cairnBOT
# deft galleon !e ```py class Person: def __init__(self, name): self.name = name # This w...

:x: Your 3.14 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "/home/main.py", line 8, in <module>
003 |     p = Person("satyam")
004 |   File "/home/main.py", line 3, in __init__
005 |     self.name = name # This will cause an AttributeError
006 |     ^^^^^^^^^
007 | AttributeError: property 'name' of 'Person' object has no setter
deft galleon
#

The error here says "property 'name' of 'Person' object has no setter"

#

That should be obvious as the 'name' property is already decorated, it should have a getter and setter. In this case, the getter is already provided as return self.name but it doesn't know or have the logic to "set" a name

#

!e
If I add the setter, it looks like this:

class Person:
  def __init__(self, name):
    self.name = name
  @property
  def name(self):
    return self.name
  @name.setter
  def name(self, new_name):
    self.name = new_name

p = Person("satyam")
print(p.name)
craggy cairnBOT
# deft galleon !e If I add the setter, it looks like this: ```py class Person: def __init__(s...

:x: Your 3.14 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "/home/main.py", line 11, in <module>
003 |     p = Person("satyam")
004 |   File "/home/main.py", line 3, in __init__
005 |     self.name = name
006 |     ^^^^^^^^^
007 |   File "/home/main.py", line 9, in name
008 |     self.name = new_name
009 |     ^^^^^^^^^
010 |   File "/home/main.py", line 9, in name
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/GM3PEG36C7GMVYDWZ67FI2MZVM

deft galleon
#

But now, it throws a different error

#
  File "/home/main.py", line 9, in name
    self.name = new_name
    ^^^^^^^^^
  [Previous line repeated 995 more times]
RecursionError: maximum recursion depth exceeded

Because it kept calling itself name attribute which is another getter which is also called name

#

So we basically confused it that the getter for name is also name. To break this recursion, we call the "private" attribute something different like _name, as thats not a decorated property that has a getter or setter

#

!e

class Person:
  def __init__(self, name):
    self._name = name
  @property
  def name(self):
    return self._name
  @name.setter
  def name(self, new_name):
    self._name = new_name

p = Person("satyam")
print(p.name)
craggy cairnBOT
deft galleon
#

It doesn't need to be _ as I pointed out earlier. You could use any other attribute name you want

#

!e

class Person:
  def __init__(self, name):
    self.temp_name = name
  @property
  def name(self):
    return self.temp_name
  @name.setter
  def name(self, new_name):
    self.temp_name = new_name

p = Person("satyam")
print(p.name)
craggy cairnBOT
fossil plinth
#

but it is common to add _ to denote the property and the attr refer to the same thing or are closely related

deft galleon
#

right. thats the usual practice and common understanding between devs that when you want something considered as a "private" attribute in a class, you add a _ to it

#

And then its just as us devs to see and understand that and be like "ah, that attribute was written to be private. We should just respect that design and variable name as it is"

echo cove
deft galleon
#

!e

class Person:
  @property
  def name(self):
    return "satyam"

p = Person()
print(p.name)
p.name = "Ajay" #Tries to change to Ajay
print(p.name)

But by doing this, you can't edit the name property anymore.

craggy cairnBOT
# deft galleon !e ```py class Person: @property def name(self): return "satyam" p = Pe...

:x: Your 3.14 eval job has completed with return code 1.

001 | satyam
002 | Traceback (most recent call last):
003 |   File "/home/main.py", line 8, in <module>
004 |     p.name = "Ajay" #Tries to change to Ajay
005 |     ^^^^^^
006 | AttributeError: property 'name' of 'Person' object has no setter
deft galleon
#

its the same if you tried in __init__ too

echo cove
#

ok

deft galleon
#

!e

class Person:
  def __init__(self):
    self._name = "satyam"
  @property
  def name(self):
    return self._name

p = Person()
print(p.name)

This works because you're not "setting" any new value. Its all hardcoded. And of course if you edit or set a new name after that, it throws that AttributeError like before

craggy cairnBOT
echo cove
#

ok

#

@deft galleon

#

this is confusing to me

deft galleon
#

that looks straightforward... hang on. gimme a min

#

!e

class Person:
  def __init__(self, name):
    self.name = name # 1) This will set the name value into the self.name property as defined in the next line. But because its a property, it needs a setter.
  @property
  def name(self):
    return self._name # 3) This is the last step. Because the value is already called and set in the setter, this self._name DOES have a value and thus is able to give back what the value is to the property.
  @name.setter
  def name(self, value):
    self._name = value # 2) So when this class instantiates, the setter here will place the "name" value into the `self._name`

p = Person("ajay")
print(p.name)
craggy cairnBOT
echo cove
#

wdym by

Because the value is already called
in the init or p.name

deft galleon
#

I've numbered them in the comments as 1) 2) and 3) for convenience

echo cove
#

yes i read that,...

#

ok

#

got it

#

that was tricky

#

it worked

#

thank you @deft galleon

#

!close

craggy cairnBOT
#
Python help channel closed with !close

This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.