2013-09-02 3 views
2

클래스/하위 클래스 외부에서 속성 생성을 제한하는 방법은 무엇입니까?속성 생성/설정 제한

__all__ = ["Employee","Salary","Wage"] 
################################################################################################## 
class Person(object): 
    def __init__(self,fname,lname,gender): 
     self.__setfname(fname) # "We are all adults." vs. "Name mangling." 
     self.__setlname(lname) 
     self.__setgender(gender) 
    def __setfname(self,fname): self.__fname = fname 
    def __setlname(self,lname): self.__lname = lname 
    def __setgender(self,gender): self.__gender = gender 
    def getname(self): return "{} {}".format(self.__fname,self.__lname) 
    def getformattedname(self): 
     if(self.__gender.lower() == "m"): 
      return "Mr. {}".format(self.getname()) 
     if(self.__gender.lower() == "f"): 
      return "Ms. {}".format(self.getname()) 
     if(self.__gender.lower() == ""): 
      return "{}".format(self.getname()) 
class Payment(object): 
    def __init__(self,amount,currency="INR"): # currency="USD" 
     self.__setamount(amount) 
     self.__setcurrency(currency) 
    def __setamount(self,amount): self.__amount = amount 
    def __setcurrency(self,currency): self.__currency = currency 
    def getamount(self): return "{}".format(self.__amount) 
    def getformattedamount(self): return "{} {}".format(self.getamount(),self.__currency) 
################################################################################################## 
################################################################################################## 
class Employee(Person): 
    def __init__(self,fname,lname,gender): super(Employee,self).__init__(fname,lname,gender) 
    def __str__(self): return self.getformattedname() 
class Salary(Payment): 
    def __init__(self,amount,currency="INR"): super(Salary,self).__init__(amount,currency) 
    def __str__(self): return self.getformattedamount() 
class Wage(Payment): 
    def __init__(self,amount,currency="INR"): super(Wage,self).__init__(amount,currency) 
    def __str__(self): return self.getformattedamount() 
################################################################################################## 

나는이 함께 확인 해요 :

e1._Person__fname = "Spam" 
s1._Payment__amount = "1000000000000000" 

하지만, 다음과 같은 코드가 생성하는 새로운 속성 :

e1.fname = "New" 
s1.amount = -10 

import re 
from com.example.model import Employee,Salary,Wage 

def printzip(l1,l2): print(list(zip([str(e) for e in l1],[str(e) for e in l2]))) 

(e1,e2) = (Employee("Sandeep","Mehta","m"),Employee("Varsha","Mehta","f")) 
(s1,s2) = (Salary(3000,"USD"),Salary(3000,"USD")) 

printzip([e1,e2],[s1,s2]) 
e1.fname = "New" 
s1.amount = -3000 
e1._Person__fname = "Spam" 
s1._Payment__amount = "3000000000000000" 

for e in enumerate([e for e in dir(e1) if not (re.search(r"^__.*__$",e))]): print(e) 
for e in enumerate([e for e in dir(s1) if not (re.search(r"^__.*__$",e))]): print(e) 
printzip([e1],[s1]) 

Python IDLE

는이 같은 것을
+0

왜 추가 속성이 문제가됩니까? – Eric

+0

속성을 private으로 만들기 위해 '__' 접두사를 사용하고 있습니다. 나는 그 "이름들"(속성들)이 수업 외부에서 접근하기를 원하지 않는다. – GLES

답변

3

할 수 :

class A: 
    def __setattr__(self, attr, val): 
     try : 
      class_name, varname = attr.split('__', 1) 
      if class_name == '_' + self.__class__.__name__: 
       self.__dict__[attr] = val 
      else: 
       raise AttributeError 
     except ValueError: 
      raise AttributeError 

데모 :

>>> %run so.py 
>>> a = A() 
>>> a._A__foo = 1 
>>> a._A__bar = 2 
>>> a._A = 2 
Traceback (most recent call last): 
    File "<ipython-input-28-eace128dbfc5>", line 1, in <module> 
    a._A = 2 
    File "/home/monty/py/so.py", line 10, in __setattr__ 
    raise AttributeError 
AttributeError 

>>> a.A__bar = 2 
Traceback (most recent call last): 
    File "<ipython-input-29-57210782cd6a>", line 1, in <module> 
    a.A__bar = 2 
    File "/home/monty/py/so.py", line 8, in __setattr__ 
    raise AttributeError 
AttributeError 

>>> a._A__spam = 3 
>>> a.__dict__ 
{'_A__foo': 1, '_A__spam': 3, '_A__bar': 2} 
+0

감사합니다. bhai! 나는 이것을 시도 할 것이다. – GLES

3

우리 수 abuse __slots__, __slots__의 주된 목적은 추가 속성을 만들지 않도록하는 것은 아니지만 :

class Person(object): 
    __slots__ = ('_Person__fname', '_Person__lname', '_Person__gender') 
    ... 

class Employee(Person): 
    __slots__ =() # All subclasses also need define __slots__ 
    ... 

e1._Person__fname = "Spam" # Fine 
e1.fname = "New"   # AttributeError: 'Employee' object has no attribute 'fname' 

__slots__을 사용하면 인스턴스의 __dict__이 생성되지 않으므로 인스턴스를 사용하는 일부 코드가 손상 될 수 있습니다.

+0

감사! 마법 같은 방법을 사용하는 것과 같은 기법이 필요했습니다. – GLES

+1

@GLES :이 솔루션을 사용하기 전에 http://stackoverflow.com/questions/472000/python-slots를 읽어보십시오. – kennytm

3

속성을 찾으십니까?

class Foo(object): 
    def __init__(self): 
     self._amount = 0 

    @property 
    def amount(self): 
     return self._amount 


f = Foo() 
print f.amount # ok 
f.amount = 100 # error 
+0

나는 주제 "decorators"를 무시하고 있었다 :) 이제는 나를 무시하고 있다는 것을 깨달았다. – GLES

6

시도하지 마십시오. 다른 사람이 수업에서하는 일은 귀하의 비즈니스가 아닙니다. 어떤 속성이 사용 가능할 것으로 예상되는지 문서화해야하며, 누군가가 그것을 남용하고 싶다면 그것은 자신의 문제가 아니라 문제입니다.

는 "우리는 모두 여기에 성인을 동의하고"는 파이썬의 철학이다.

+0

(y) @ "다른 사람들이 당신의 직업과 어떤 관련이 없습니까?" 그러나 ... 다른 누군가가 모델/데이터베이스가 영향을 받기 시작하는 속성을 남용하기 시작하면 내 사업입니다. – GLES

+0

나는 다니엘과 같은 의견이다. 자동차를 사고 더 이상 작동하지 않는 방식으로 브레이크를 조작하면 이는 자동차 제조업체의 문제가 아니라 귀하 자신의 문제입니다. 라이브러리의 문서화되지 않은 기능을 사용하는 경우 갑자기 해당 기능이 더 이상 지원되지 않는 경우 귀하의 비즈니스가 아니라 도서관의 작가의 비즈니스가됩니다. 사용자가 코드를 악용하는 경우 귀하의 코드가 귀하의 비즈니스가 아닙니다. "의도 한 대로만 코드 사용". 그냥 내 두 센트. – Hyperboreus

+0

@GLES는 동료이므로 데이터베이스를 해킹하지 않아도 신뢰할 수는 없습니다. –

관련 문제