-3

I've read all the similar posts regarding this topic but none that I found related to my problem in a way that helped me figure out what was happening.

class A: def __init__(self, value): self.__value = value self.__conn = httpsconnection # Specifics don't matter class B(A): def __init__(self, id, type, value): super().__init__(value) self.data = self.__create_sub_class(id, type) def __create_sub_class(self, id, type): self.__conn.request(...) ... return data class C(B): def __init__(self, id, value): super().__init__(id, externalVariable, value) 

The error I am getting is AttributeError: 'C' object has no attribute '_B__conn'

Shouldn't class C inherit the variable from B which inherited it from A?

4
  • 2
    Why are you using double-underscore names? Those are explicitly designed to avoid inheritability. Commented Sep 3, 2017 at 11:51
  • docs.python.org/3/tutorial/classes.html#private-variables Commented Sep 3, 2017 at 11:53
  • @MartijnPieters They're my private variables. A habit I picked up in another language when I was learning to program. Commented Sep 3, 2017 at 11:53
  • @Spedwards: there is no privacy model in Python, other than class-private names, and your use cases doesn't fit their goal. Commented Sep 3, 2017 at 11:54

1 Answer 1

1

Do not use leading double-underscore names if you want to use those names in subclasses. The __name is explicitly designed to make the name class private, that is, only useful for the exact class. The idea is that you can use such names in a framework without then limiting what names subclasses can use.

Such names are mangled at compile time; they have _ClassName prefixed (with the current class name). Simply use single underscore names if you want to signal that a name is internal (Python has no actual privacy model, names are always accessible):

class A: def __init__(self, value): self._value = value self._conn = httpsconnection # Specifics don't matter class B(A): def __init__(self, id, type, value): super().__init__(value) self.data = self._create_sub_class(id, type) def _create_sub_class(self, id, type): self._conn.request(...) ... return data 

See Reserved classes of identifiers in the lexical analysis documentation:

__*
Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes.

and the referenced documentation on names:

Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam. This transformation is independent of the syntactical context in which the identifier is used.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I didn't know about the whole name-mangling. I don't know why but I've always preferred using double underscores over single. I guess that'll have to change now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.