본문 바로가기

Coding

[pep8] Private Attributes

Private 변수

Private 변수

Java나 C++에서 흔히 사용하는 Private 변수.
객체로부터 직접접근이나 상속하고 싶지 않은 멤버 변수에 사용한다.

Pep8 Coding Rule 가이드에 따르면, private attribute를 다음과 같이 가이드하고 있다.

Public vs Non-public

Always decide whether a class’s methods and instance variables (collectively: “attributes”) should be public or non-public. If in doubt, choose non-public; it’s easier to make it public later than to make a public attribute non-public.

멤버 함수나 멤버 변수가 Public일지 Non-public일지 항상 결정하라. 고민이 된다면 그냥 Non-public으로 가라. 후에 디자인이 변경된다고 해도, Non-public을 Public으로 바꾸는게 더 쉽다.

Backward-compatibility

Public attributes are those that you expect unrelated clients of your class to use, with your commitment to avoid backwards incompatible changes. Non-public attributes are those that are not intended to be used by third parties; you make no guarantees that non-public attributes won’t change or even be removed.
Public 변수는 누구나 사용할 수 있는 변수이다. 따라서 디자인할 때 ‘하위호환성’을 꼭 지켜야 한다 (코드가 패치되더라도 해당 변수는 유지되어야 하며 동일한 의미를 지녀야한다.). Non-public 변수는 마음대로 삭제하고 수정해도 된다는 의미를 갖는다.

Don’t use “Private”

We don’t use the term “private” here, since no attribute is really private in Python (without a generally unnecessary amount of work).

중요! Python에서 Private은 존재하지 않으므로 “Private”이라는 용어를 사용하지 말자.

: 따라서 앞에서 설명한 Private 변수의 기능 중, 객체로부터 직접접근 차단은 지원하지 않으나, 상속하고 싶지 않은 멤버 변수의 표현은 지원한다. (Naming Rule에 의해 개발자 의도 전달)

Inheritance

If your class is intended to be subclassed, and you have attributes that you do not want subclasses to use, consider naming them with double leading underscores and no trailing underscores. This invokes Python’s name mangling algorithm, where the name of the class is mangled into the attribute name. This helps avoid attribute name collisions should subclasses inadvertently contain attributes with the same name.

상속을 의도하고 코드를 작성할 때, Subclass들이 멤버 변수 사용을 원하지 않는다면 Underscore()를 두 개 붙여 표현한다. 두 개를 붙이면 Python 자체적으로 해당 멤버변수 이름을 _Class명_변수명으로 저장함 (Name mangling algorithm). 이러면 실수로 Subclass에서 해당 변수명을 사용하더라도 Name Conflict가 발생하지 않음.


class Flyable:
 __can_fly = True

class Chicken(Flyable):
 __can_fly = False

# Result of dir(Chicken)
['_Chicken__can_fly',
'_Flyable__can_fly',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__']