SlideShare a Scribd company logo
PYTHON
DESCRIPTOR
이해하기
Moon Yong Joon
Descriptor 란
Descriptor 란
 __get__(self, instance, class), __set__(self,
instance, value), __delete__(self, instance )
 3개의 메소드를 가지는 클래스
 Self는 Descriptor 클래스의 인스턴스
 Instance는 class로 생성되는 인스턴스
 다른 클래스 변수에 descriptor 인스턴스를 할
당해서 사용
Descriptor aggregation 구조
인스턴스에서 클래스변수(aggregation)를 호출하
면 descriptor 인스턴스가 descriptor 메소드를
호출하여 인스턴스 내부 변수와 할당값을 세팅
Descriptor
class
User
defined
class
변수
Descriptor
instance
User
defined
instance
_변수
__init__
__get__
__set__
__delete__
1. 인스턴스.변수 호출
2. 클래스 내의 변수 확
인
3. Descriptor 인스턴
스가 get/set 메소
드 호출
4. 인스턴스.__dict__에
_변수 할당
Descriptor aggregation 주의사
항 : 변수명
사용자 인스턴스 저장되는 변수를 클래스 내부에
정의된 변수와 구별 필요 ( _변수명)
Descriptor
class
User
defined
class
변수
Descriptor
instance
User
defined
instance
_변수
__init__
__get__
__set__
__delete__
1. 인스턴스.변수 호출
2. 클래스 내의 변수 확
인
3. Descriptor 인스턴
스가 get/set 메소
드 호출
4. 인스턴스.__dict__에
_변수 할당
Descriptor aggregation 주의사
항 : get
인스턴스.변수명을 사용하면 __get__가 호출되므
로 인스턴스._변수명이 미존재하므로 초기값 정의
필요
Descriptor
class
User
defined
class
변수
Descriptor
instance
User
defined
instance
_변수
__init__
__get__
__set__
__delete__
1. 인스턴스.변수 호출
2. 클래스 내의 변수 확
인
3. Descriptor 인스턴
스가 get/set 메소
드 호출
4. 인스턴스.__dict__에
_변수 할당
Descriptor 상속 구조
Descriptor 상속관계로 구현시 실제 descriptor 인
스턴스에 값을 보관하여 처, 실제 __get__을 사용
해서 값을 검색해야 함
Descriptor
class
User
defined
class
User
defined
instance
변수
__init__
__get__
Descriptor
인스턴스
변수
Descriptor 상속 구조 사용
descriptor 클래스를 상속해서 get 만 사용하는
경우
class D(object) :
def __init__(self, x=None) :
self.x = x
def __get__(self,instance=None,cls=None) :
return self.x
class D1(D) :
def __init__(self, x,y) :
self.x = D(x)
self.y = D(y)
d1 = D1(2,3)p
rint (" d1")
print (d1.__dict__)
print (d1.x)
print(d1.y)
print (" direct call",d1.x.__get__(), d1.y.__get__())
print (" Class binding call x ", D1.__get__(d1.x,d1.x))
print (" Class binding call y ", D1.__get__(d1.y,d1.y))
print (" class binding",type(d1).__get__(d1.x,d1.x))
D1
{'x': <__main__.D object at
0x113f46400>, 'y':
<__main__.D object at
0x113f461d0>}
<__main__.D object at
0x113f46400>
<__main__.D object at
0x113f461d0>
direct call 2 3
Class binding call x 2
Class binding call y 3
class binding 2
Descriptor 구성
Descriptor 처리 절차
Descriptor class를 생성하여 실제 구현 클래스
내부의 속성에 대한 init/getter/setter/deleter
를 통제할 수 있도록 구조화
Class Decriptor :
def __init__
def __get__
def __set__
def __del__
class Person() :
name= Descriptor()
user = Person()
user.name = ‘Dahl’
Descriptor class 생성
구현 class 정의시 속성에
대한인스턴스 생성
구현class에 대한 인스턴
스 생성 및 인스턴스 속성
에 값 세팅
Descriptor class 정의
클래스에 인스턴스를 관리하는 생성자와 실제 인스
턴스의 값을 관리 get/set/delete 메소드 정의
class Descriptor(object)
def __init__(self,name):
self.name = ‘_’ + str(name)
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
instance.__dict__[self.name] = value
def __delete__(self, instance):
del instance.__dict__[self.name]
인스턴스 객체의 변수명
으로 세팅될 변수명 저장
__get__/__set__ 검색1
 getattr,setattr 함수를 이용해서 내부의 값을
직접 검색 및 갱신
def __get__(self, instance, owner):
return getattr(instance, self.name)
def __set__(self, instance, value):
setattr(instance,self.name,value)
__get__/__set__ 검색2
 Instance 내부의 값을 직접 검색
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
instance.__dict__[self.name] = value
Data descriptor 여부 확인
 Inspect 모듈을 이용해서 data descriptor 여
부 확인
import inspect
print(inspect.isdatadescriptor(descriptor()) #true
Descriptor 사용 class 정의/실행
1. 구현 클래스에는 속성에 descriptor인스턴스 생성
2. 인스턴스 객체의 변수에 직접 값을 할당(set)
3. 인스턴스 객체의 변수로 조회(get)
class Person(object):
name = Descriptor(“name”)
user = Person()
print user.__dict__ # {}
user.name = 'john smith‘
print user.__dict__ # {'_name': 'john smith'}
print "user.name ",user.name # user.name john smith
인스턴스의 변수와
내부 관리 변수의
name을 상이하게
관리도 가능
Descriptor 메소드 호출 예시
2개 호출 처리는 동일 한 결과가 나온다.
실제 구현시 첫번째 방식이 가독성이 높음
user = Person()
user.name = 'john smith’ # Descriptor.__set__ 호출
print user.name # Descriptor.__get__ 호출
print user.__dict__
user1 = Person()
Descriptor.__set__(Descriptor(),user1,"dahl")
Descriptor.__get__(Descriptor(),user1,Descriptor)
print user1.__dict__
Descriptor : 함수처리
Descriptor 정의
Descriptor 클래스 정의
class descriptor(object) :
def __init__(self,name,func):
self.name = '_'+ str(name)
self.func = func
def __get__(self, instance, owner):
return getattr(instance,self.name)
def __set__(self, instance, value):
setattr(instance,self.name,value)
Value에 함수 할당
Descriptor 실행
함수를 정의하고 할당해서 실행
def add(x,y) :
return x+y
class A(object) :
add = descriptor("add",add)
a = A()
print(a.__dict__)
print(A.__dict__)
print(a.add(5,5))
print(type(a.__dict__['_add']))
print(A.__dict__['add'])
print(a.add)
print(A.__dict__['add'].__dict__)
da = descriptor("aaa","")
print(type(da), da.__dict__, da.name)
{}
{'add': <__main__.descriptor object at
0x114140358>, '__weakref__': <attribute
'__weakref__' of 'A' objects>, '__dict__': <attribute
'__dict__' of 'A' objects>, '__module__': '__main__',
'__doc__': None}{'_add': <function add at
0x114135730>}
10
<class 'function'>
<__main__.descriptor object at 0x114140358>
<function add at 0x114135730>
{'name': '_add', 'func': <function add at
0x114135730>}
<class '__main__.descriptor'> {'name': '_aaa', 'func': ''}
_aaa
Descriptor 종류
Descriptor 종류
Method descriptor와 Data descripter 로 구분
 Method descriptor는 __get__(self, instance,
owner) 구현
 Data descriptor는 __get__(self, instance,
owner), __set__(self,instance, value) or
__delete__(self, instance) 구현
Creating data descriptor
Data Descriptor 클래스를 생성해서 처리하는
방법
class Descriptor(object):
def __init__(self):
self._name = ''
def __get__(self, instance, owner):
print "Getting: %s" % self._name
return self._name
def __set__(self, instance, name):
print "Setting: %s" % name
self._name = name.title()
def __delete__(self, instance):
print "Deleting: %s" %self._name
del self._name
class Person(object):
name = Descriptor()
>>> user = Person()
>>> user.name = 'john smith'
Setting: john smith
>>> user.name
Getting: John Smith
'John Smith‘
>>> del user.name
Deleting: John Smith
여러 개 속성변수 처리하기
Descriptor : init 메소드 수정
Descriptor class에 생성자 메소드에 변수명, 변
수 타입, 변수값을 받아 생성하도록 만듦
Class Decriptor :
# 변수명, 값타입, 디폴트값,
def __init__(self, var_name, var_type, var_default) :
self.var_name = “_”+var_name
self.var_type = var_type
self.var_default = var_default if var_default else type()
Descriptor : get/set 함수 수정
Descriptor class에 생성자 메소드에 변수명, 변
수 타입, 변수값을 받아 생성하도록 만듦
Class Decriptor :
def __get__(self, instance, cls):
return getattr(instance, self.name, self.default)
def __set__(self,instance,value):
if not isinstance(value,self.type):
raise TypeError("Must be a %s" % self.type)
setattr(instance,self.name,value)
def __delete__(self,instance):
raise AttributeError("Can't delete attribute")
# 처리시 주의 사항
setattr(instance,self.name,va
lue)
 self.name의 “_” 없는 값을
넣을 경우 런타임오류 발생
RuntimeError: maximum
recursion depth exceeded
while calling a Python object
구현 class 처리:
클래스 내부의 변수에 descriptor 인스턴스를 생
성함.
class Person(object):
name =Descriptor ("name",str)
age = Descriptor("age",int,42)
user = Person()
Property 처리
Creating Property- 객체 직접 정의(1)
인스턴스 객체의 변수 접근을 메소드로 제약하기 위해서는
Property 객체로 인스턴스 객체의 변수를 Wrapping 해야 함
property(fget=None, fset=None, fdel=None, doc=None)
class P:
def __init__(self,x):
self.x = x
def getx(self) :
return self.x
def setx(self, x) :
self.x = x
def delx(self) :
del self.x
x = property(getx,setx,delx," property test ")
Getter, setter, deleter 메
소드를 정의
인스턴스 객체의 변수명과
동일하게 Property 객체 생
성(내부에 _x 생김)
Creating Property–객체 직접 정의(2)
실제 인스턴스 객체의 변수에 접근하면 Property
객체의 메소드를 호출하여 처리되고 인스턴스 객
체의 변수값이 변경됨
p1 = P(1001)
print id(p1.x)
print P.__dict__['x']
print id(p1.__dict__['x'])
print p1.x
p1.x = -12
print p1.x
print p1.__dict__
#처리결과값
44625868
<property object at
0x02C1D4E0>
44625868
1001
-12
{'x': -12}
Decorator 처리
Creating Property decorator(1)
인스턴스 객체의 변수 접근을 메소드로 제약하기 위해서는
Property 객체로 인스턴스 객체의 변수를 Wrapping 해야 함
property(fget=None, fset=None, fdel=None, doc=None)
class P: def __init__(self,x):
self._x = x
@property
def x(self):
return self._x
@x.setter
def x(self, x):
self._x = x
@x.deleter
def x(self):
del self._x
Getter, setter, deleter 메
소드를 정의
인스턴스 객체의 변수명과
동일하게 Property 객체 생
성(내부에 _x 생김)
Creating Property decorator(2)
Property 객체 생성하여 처리하는 방식과 동일
p1 = P(1001)
print(id(p1.x))
print(p1.x)
p1.x = -12
print (p1.x)
print (p1.__dict__)
#처리결과값
46261915041001
-12
{'_x': -12}
내장함수를 통한 객체접근
Built-in 내장함수
내장함수를 이용하여 객체의 속성에 대한 접근
object.x  getattr()
object.x = value  setattr()
del(object.x)  delattr()
함수 구조
getattr(object, name[, default])
setattr(object, name, value)
delattr(object, name)
hasattr(object, name)
callable(object)
Built-in 내장함수: 예시 1
객체의 속성을 접근하고변경
class A():
def __init__(self, name,age) :
self.name = name
self.age = age
a = A('dahl',50)
if hasattr(a,"name") :
print getattr(a,"name")
setattr(a,"name","Moon")
print getattr(a,"name")
else :
pass
if hasattr(a,"age") :
print getattr(a,"age")
else :
pass
#처리결과값
dahl
Moon
50
Built-in 내장함수: 예시 2
메소드 및 함수여부 확인 후 실행
class A():
def __init__(self, name,age) :
self.name = name
self.age = age
def in_set(self,name,default) :
self.__dict__[name] = default
print self.__dict__[name]
a = A('dahl',50)
def add(x,y) :
return x+y
if callable(add) :
add(5,6)
else :
pass
if callable(a.in_set) :
a.in_set('age',20)
else:
pass
#처리결과값
dahl
Moon
50
20

More Related Content

PPTX
파이썬 객체 클래스 이해하기
PPTX
파이썬 프로퍼티 디스크립터 이해하기
PPTX
파이썬+클래스+구조+이해하기 20160310
PPTX
파이썬 namespace Binding 이해하기
PPTX
파이썬 Special method 이해하기
PPTX
파이썬 class 및 function namespace 이해하기
PPTX
파이썬+객체지향+이해하기 20160131
PPTX
python data model 이해하기
파이썬 객체 클래스 이해하기
파이썬 프로퍼티 디스크립터 이해하기
파이썬+클래스+구조+이해하기 20160310
파이썬 namespace Binding 이해하기
파이썬 Special method 이해하기
파이썬 class 및 function namespace 이해하기
파이썬+객체지향+이해하기 20160131
python data model 이해하기

What's hot (20)

PPTX
파이썬 class 및 인스턴스 생성 이해하기
PPTX
파이썬 심화
PPTX
파이썬+주요+용어+정리 20160304
PPTX
파이썬 반복자 생성자 이해하기
PPTX
파이썬+함수이해하기 20160229
PPTX
파이썬 Xml 이해하기
PPTX
파이썬 iterator generator 이해하기
PPTX
파이썬 xml 이해하기
PPTX
파이썬 함수 이해하기
PPTX
파이썬+데이터+구조+이해하기 20160311
PPTX
엘라스틱서치 이해하기 20160612
PPTX
파이썬정리 20160130
PPTX
파이썬 플라스크 이해하기
PPTX
파이썬+Json+이해하기 20160301
PPTX
Jupyter notebook 이해하기
PPTX
파이썬 내부 데이터 검색 방법
PPTX
파이썬 데이터 검색
PPTX
파이썬 파일처리 이해하기
PPTX
파이썬+함수 데코레이터+이해하기 20160229
PPTX
Python+numpy pandas 4편
파이썬 class 및 인스턴스 생성 이해하기
파이썬 심화
파이썬+주요+용어+정리 20160304
파이썬 반복자 생성자 이해하기
파이썬+함수이해하기 20160229
파이썬 Xml 이해하기
파이썬 iterator generator 이해하기
파이썬 xml 이해하기
파이썬 함수 이해하기
파이썬+데이터+구조+이해하기 20160311
엘라스틱서치 이해하기 20160612
파이썬정리 20160130
파이썬 플라스크 이해하기
파이썬+Json+이해하기 20160301
Jupyter notebook 이해하기
파이썬 내부 데이터 검색 방법
파이썬 데이터 검색
파이썬 파일처리 이해하기
파이썬+함수 데코레이터+이해하기 20160229
Python+numpy pandas 4편
Ad

Similar to 파이썬 Descriptor이해하기 20160403 (20)

PDF
파이썬 모듈 패키지
PPTX
파이썬 Collections 모듈 이해하기
PPTX
게임프로그래밍입문 7
PPTX
Swt J Face 2/3
PPT
Python class
PDF
[Swift] Properties
PPTX
Swift3 : class and struct(+property+method)
DOCX
Javascript 완벽 가이드 정리
PPTX
Refelction의 개념과 RTTR 라이브러리
PPTX
Java, android 스터티2
PDF
The c++ programming language 10장 클래스 발표
PPTX
Effective c++(chapter3,4)
PPTX
C++ stl
PDF
Java class
PDF
Java_05 class
PPTX
포트폴리오에서 사용한 모던 C++
PDF
[IT기술칼럼 #4] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
PPTX
Fluent Python - Chapter 8
PDF
Python
PPTX
Xe hack
파이썬 모듈 패키지
파이썬 Collections 모듈 이해하기
게임프로그래밍입문 7
Swt J Face 2/3
Python class
[Swift] Properties
Swift3 : class and struct(+property+method)
Javascript 완벽 가이드 정리
Refelction의 개념과 RTTR 라이브러리
Java, android 스터티2
The c++ programming language 10장 클래스 발표
Effective c++(chapter3,4)
C++ stl
Java class
Java_05 class
포트폴리오에서 사용한 모던 C++
[IT기술칼럼 #4] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
Fluent Python - Chapter 8
Python
Xe hack
Ad

More from Yong Joon Moon (20)

PPTX
rust ownership
PDF
Scala namespace scope
PDF
Scala companion object
PDF
Scala block expression
PDF
Scala self type inheritance
PDF
Scala variable
PDF
Scala type class pattern
PDF
Scala match pattern
PDF
Scala implicit
PDF
Scala type args
PPTX
Scala trait usage
PPTX
Scala nested function generic function
PDF
Scala dir processing
PDF
Scala syntax function
PDF
스칼라 클래스 이해하기 _Scala class understanding
PPTX
파이썬 문자열 이해하기
PPTX
파이썬 엑셀_csv 처리하기
PPTX
Python+numpy pandas 3편
PPTX
Python+numpy pandas 2편
PPTX
Python+numpy pandas 1편
rust ownership
Scala namespace scope
Scala companion object
Scala block expression
Scala self type inheritance
Scala variable
Scala type class pattern
Scala match pattern
Scala implicit
Scala type args
Scala trait usage
Scala nested function generic function
Scala dir processing
Scala syntax function
스칼라 클래스 이해하기 _Scala class understanding
파이썬 문자열 이해하기
파이썬 엑셀_csv 처리하기
Python+numpy pandas 3편
Python+numpy pandas 2편
Python+numpy pandas 1편

파이썬 Descriptor이해하기 20160403

  • 3. Descriptor 란  __get__(self, instance, class), __set__(self, instance, value), __delete__(self, instance )  3개의 메소드를 가지는 클래스  Self는 Descriptor 클래스의 인스턴스  Instance는 class로 생성되는 인스턴스  다른 클래스 변수에 descriptor 인스턴스를 할 당해서 사용
  • 4. Descriptor aggregation 구조 인스턴스에서 클래스변수(aggregation)를 호출하 면 descriptor 인스턴스가 descriptor 메소드를 호출하여 인스턴스 내부 변수와 할당값을 세팅 Descriptor class User defined class 변수 Descriptor instance User defined instance _변수 __init__ __get__ __set__ __delete__ 1. 인스턴스.변수 호출 2. 클래스 내의 변수 확 인 3. Descriptor 인스턴 스가 get/set 메소 드 호출 4. 인스턴스.__dict__에 _변수 할당
  • 5. Descriptor aggregation 주의사 항 : 변수명 사용자 인스턴스 저장되는 변수를 클래스 내부에 정의된 변수와 구별 필요 ( _변수명) Descriptor class User defined class 변수 Descriptor instance User defined instance _변수 __init__ __get__ __set__ __delete__ 1. 인스턴스.변수 호출 2. 클래스 내의 변수 확 인 3. Descriptor 인스턴 스가 get/set 메소 드 호출 4. 인스턴스.__dict__에 _변수 할당
  • 6. Descriptor aggregation 주의사 항 : get 인스턴스.변수명을 사용하면 __get__가 호출되므 로 인스턴스._변수명이 미존재하므로 초기값 정의 필요 Descriptor class User defined class 변수 Descriptor instance User defined instance _변수 __init__ __get__ __set__ __delete__ 1. 인스턴스.변수 호출 2. 클래스 내의 변수 확 인 3. Descriptor 인스턴 스가 get/set 메소 드 호출 4. 인스턴스.__dict__에 _변수 할당
  • 7. Descriptor 상속 구조 Descriptor 상속관계로 구현시 실제 descriptor 인 스턴스에 값을 보관하여 처, 실제 __get__을 사용 해서 값을 검색해야 함 Descriptor class User defined class User defined instance 변수 __init__ __get__ Descriptor 인스턴스 변수
  • 8. Descriptor 상속 구조 사용 descriptor 클래스를 상속해서 get 만 사용하는 경우 class D(object) : def __init__(self, x=None) : self.x = x def __get__(self,instance=None,cls=None) : return self.x class D1(D) : def __init__(self, x,y) : self.x = D(x) self.y = D(y) d1 = D1(2,3)p rint (" d1") print (d1.__dict__) print (d1.x) print(d1.y) print (" direct call",d1.x.__get__(), d1.y.__get__()) print (" Class binding call x ", D1.__get__(d1.x,d1.x)) print (" Class binding call y ", D1.__get__(d1.y,d1.y)) print (" class binding",type(d1).__get__(d1.x,d1.x)) D1 {'x': <__main__.D object at 0x113f46400>, 'y': <__main__.D object at 0x113f461d0>} <__main__.D object at 0x113f46400> <__main__.D object at 0x113f461d0> direct call 2 3 Class binding call x 2 Class binding call y 3 class binding 2
  • 10. Descriptor 처리 절차 Descriptor class를 생성하여 실제 구현 클래스 내부의 속성에 대한 init/getter/setter/deleter 를 통제할 수 있도록 구조화 Class Decriptor : def __init__ def __get__ def __set__ def __del__ class Person() : name= Descriptor() user = Person() user.name = ‘Dahl’ Descriptor class 생성 구현 class 정의시 속성에 대한인스턴스 생성 구현class에 대한 인스턴 스 생성 및 인스턴스 속성 에 값 세팅
  • 11. Descriptor class 정의 클래스에 인스턴스를 관리하는 생성자와 실제 인스 턴스의 값을 관리 get/set/delete 메소드 정의 class Descriptor(object) def __init__(self,name): self.name = ‘_’ + str(name) def __get__(self, instance, owner): return instance.__dict__[self.name] def __set__(self, instance, value): instance.__dict__[self.name] = value def __delete__(self, instance): del instance.__dict__[self.name] 인스턴스 객체의 변수명 으로 세팅될 변수명 저장
  • 12. __get__/__set__ 검색1  getattr,setattr 함수를 이용해서 내부의 값을 직접 검색 및 갱신 def __get__(self, instance, owner): return getattr(instance, self.name) def __set__(self, instance, value): setattr(instance,self.name,value)
  • 13. __get__/__set__ 검색2  Instance 내부의 값을 직접 검색 def __get__(self, instance, owner): return instance.__dict__[self.name] def __set__(self, instance, value): instance.__dict__[self.name] = value
  • 14. Data descriptor 여부 확인  Inspect 모듈을 이용해서 data descriptor 여 부 확인 import inspect print(inspect.isdatadescriptor(descriptor()) #true
  • 15. Descriptor 사용 class 정의/실행 1. 구현 클래스에는 속성에 descriptor인스턴스 생성 2. 인스턴스 객체의 변수에 직접 값을 할당(set) 3. 인스턴스 객체의 변수로 조회(get) class Person(object): name = Descriptor(“name”) user = Person() print user.__dict__ # {} user.name = 'john smith‘ print user.__dict__ # {'_name': 'john smith'} print "user.name ",user.name # user.name john smith 인스턴스의 변수와 내부 관리 변수의 name을 상이하게 관리도 가능
  • 16. Descriptor 메소드 호출 예시 2개 호출 처리는 동일 한 결과가 나온다. 실제 구현시 첫번째 방식이 가독성이 높음 user = Person() user.name = 'john smith’ # Descriptor.__set__ 호출 print user.name # Descriptor.__get__ 호출 print user.__dict__ user1 = Person() Descriptor.__set__(Descriptor(),user1,"dahl") Descriptor.__get__(Descriptor(),user1,Descriptor) print user1.__dict__
  • 18. Descriptor 정의 Descriptor 클래스 정의 class descriptor(object) : def __init__(self,name,func): self.name = '_'+ str(name) self.func = func def __get__(self, instance, owner): return getattr(instance,self.name) def __set__(self, instance, value): setattr(instance,self.name,value) Value에 함수 할당
  • 19. Descriptor 실행 함수를 정의하고 할당해서 실행 def add(x,y) : return x+y class A(object) : add = descriptor("add",add) a = A() print(a.__dict__) print(A.__dict__) print(a.add(5,5)) print(type(a.__dict__['_add'])) print(A.__dict__['add']) print(a.add) print(A.__dict__['add'].__dict__) da = descriptor("aaa","") print(type(da), da.__dict__, da.name) {} {'add': <__main__.descriptor object at 0x114140358>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__dict__': <attribute '__dict__' of 'A' objects>, '__module__': '__main__', '__doc__': None}{'_add': <function add at 0x114135730>} 10 <class 'function'> <__main__.descriptor object at 0x114140358> <function add at 0x114135730> {'name': '_add', 'func': <function add at 0x114135730>} <class '__main__.descriptor'> {'name': '_aaa', 'func': ''} _aaa
  • 21. Descriptor 종류 Method descriptor와 Data descripter 로 구분  Method descriptor는 __get__(self, instance, owner) 구현  Data descriptor는 __get__(self, instance, owner), __set__(self,instance, value) or __delete__(self, instance) 구현
  • 22. Creating data descriptor Data Descriptor 클래스를 생성해서 처리하는 방법 class Descriptor(object): def __init__(self): self._name = '' def __get__(self, instance, owner): print "Getting: %s" % self._name return self._name def __set__(self, instance, name): print "Setting: %s" % name self._name = name.title() def __delete__(self, instance): print "Deleting: %s" %self._name del self._name class Person(object): name = Descriptor() >>> user = Person() >>> user.name = 'john smith' Setting: john smith >>> user.name Getting: John Smith 'John Smith‘ >>> del user.name Deleting: John Smith
  • 23. 여러 개 속성변수 처리하기
  • 24. Descriptor : init 메소드 수정 Descriptor class에 생성자 메소드에 변수명, 변 수 타입, 변수값을 받아 생성하도록 만듦 Class Decriptor : # 변수명, 값타입, 디폴트값, def __init__(self, var_name, var_type, var_default) : self.var_name = “_”+var_name self.var_type = var_type self.var_default = var_default if var_default else type()
  • 25. Descriptor : get/set 함수 수정 Descriptor class에 생성자 메소드에 변수명, 변 수 타입, 변수값을 받아 생성하도록 만듦 Class Decriptor : def __get__(self, instance, cls): return getattr(instance, self.name, self.default) def __set__(self,instance,value): if not isinstance(value,self.type): raise TypeError("Must be a %s" % self.type) setattr(instance,self.name,value) def __delete__(self,instance): raise AttributeError("Can't delete attribute") # 처리시 주의 사항 setattr(instance,self.name,va lue)  self.name의 “_” 없는 값을 넣을 경우 런타임오류 발생 RuntimeError: maximum recursion depth exceeded while calling a Python object
  • 26. 구현 class 처리: 클래스 내부의 변수에 descriptor 인스턴스를 생 성함. class Person(object): name =Descriptor ("name",str) age = Descriptor("age",int,42) user = Person()
  • 28. Creating Property- 객체 직접 정의(1) 인스턴스 객체의 변수 접근을 메소드로 제약하기 위해서는 Property 객체로 인스턴스 객체의 변수를 Wrapping 해야 함 property(fget=None, fset=None, fdel=None, doc=None) class P: def __init__(self,x): self.x = x def getx(self) : return self.x def setx(self, x) : self.x = x def delx(self) : del self.x x = property(getx,setx,delx," property test ") Getter, setter, deleter 메 소드를 정의 인스턴스 객체의 변수명과 동일하게 Property 객체 생 성(내부에 _x 생김)
  • 29. Creating Property–객체 직접 정의(2) 실제 인스턴스 객체의 변수에 접근하면 Property 객체의 메소드를 호출하여 처리되고 인스턴스 객 체의 변수값이 변경됨 p1 = P(1001) print id(p1.x) print P.__dict__['x'] print id(p1.__dict__['x']) print p1.x p1.x = -12 print p1.x print p1.__dict__ #처리결과값 44625868 <property object at 0x02C1D4E0> 44625868 1001 -12 {'x': -12}
  • 31. Creating Property decorator(1) 인스턴스 객체의 변수 접근을 메소드로 제약하기 위해서는 Property 객체로 인스턴스 객체의 변수를 Wrapping 해야 함 property(fget=None, fset=None, fdel=None, doc=None) class P: def __init__(self,x): self._x = x @property def x(self): return self._x @x.setter def x(self, x): self._x = x @x.deleter def x(self): del self._x Getter, setter, deleter 메 소드를 정의 인스턴스 객체의 변수명과 동일하게 Property 객체 생 성(내부에 _x 생김)
  • 32. Creating Property decorator(2) Property 객체 생성하여 처리하는 방식과 동일 p1 = P(1001) print(id(p1.x)) print(p1.x) p1.x = -12 print (p1.x) print (p1.__dict__) #처리결과값 46261915041001 -12 {'_x': -12}
  • 34. Built-in 내장함수 내장함수를 이용하여 객체의 속성에 대한 접근 object.x  getattr() object.x = value  setattr() del(object.x)  delattr() 함수 구조 getattr(object, name[, default]) setattr(object, name, value) delattr(object, name) hasattr(object, name) callable(object)
  • 35. Built-in 내장함수: 예시 1 객체의 속성을 접근하고변경 class A(): def __init__(self, name,age) : self.name = name self.age = age a = A('dahl',50) if hasattr(a,"name") : print getattr(a,"name") setattr(a,"name","Moon") print getattr(a,"name") else : pass if hasattr(a,"age") : print getattr(a,"age") else : pass #처리결과값 dahl Moon 50
  • 36. Built-in 내장함수: 예시 2 메소드 및 함수여부 확인 후 실행 class A(): def __init__(self, name,age) : self.name = name self.age = age def in_set(self,name,default) : self.__dict__[name] = default print self.__dict__[name] a = A('dahl',50) def add(x,y) : return x+y if callable(add) : add(5,6) else : pass if callable(a.in_set) : a.in_set('age',20) else: pass #처리결과값 dahl Moon 50 20