최근 에 getattr()
함수 에 대해 읽었습니다 . 문제는 여전히 사용법에 대한 아이디어를 파악할 수 없다는 것입니다. 내가 대해 이해할 수있는 유일한 방법은 getattr()
즉 getattr(li, "pop")
호출과 동일합니다 li.pop
.
나는 책이 런타임까지 함수의 이름을 알지 못하고 함수에 대한 참조를 얻는 방법을 언급했을 때 이해하지 못했습니다. 어쩌면 이것은 일반적으로 프로그래밍에서 멍청한 것일 수도 있습니다. 누구든지 주제에 대해 약간의 빛을 비출 수 있습니까? 언제 어떻게 정확하게 사용해야합니까?
답변
getattr(object, 'x')
완전히 동등 에 object.x
.
있다 다음 두 가지 경우에만getattr
유용 할 수는.
object.x
원하는 속성을 미리 알지 못하므로 (문자열에서 나옴) 쓸 수 없습니다 . 메타 프로그래밍에 매우 유용합니다.- 기본값을 제공하려고합니다.
object.y
가 없으면를AttributeError
발생y
시킵니다. 그러나getattr(object, 'y', 5)
돌아올 것이다5
.
답변
파이썬의 객체는 속성 (데이터 속성 및 그와 함께 작동하는 함수)을 가질 수 있습니다. 실제로 모든 객체에는 내장 속성이 있습니다.
예를 들어 객체를 가지고 person
, 그 몇 가지 속성이 있습니다 name
, gender
등
이러한 속성은 (그 방법이나 데이터 객체 일) 보통 쓰기 액세스 : person.name
, person.gender
, person.the_method()
, 등
그러나 프로그램을 작성할 때 속성의 이름을 모른다면 어떻게해야합니까? 예를 들어, 속성 이름이라는 변수에 저장되어 attr_name
있습니다.
만약
attr_name = 'gender'
그런 다음 글을 쓰는 대신
gender = person.gender
당신은 쓸 수 있습니다
gender = getattr(person, attr_name)
연습 :
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
>>> class Person():
... name = 'Victor'
... def say(self, what):
... print(self.name, what)
...
>>> getattr(Person, 'name')
'Victor'
>>> attr_name = 'name'
>>> person = Person()
>>> getattr(person, attr_name)
'Victor'
>>> getattr(person, 'say')('Hello')
Victor Hello
getattr
올릴 AttributeError
지정된 이름을 가지는 속성이 객체로 존재하지 않는 경우 :
>>> getattr(person, 'age')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'
그러나 세 번째 인수로 기본값을 전달할 수 있습니다. 이러한 속성이 존재하지 않으면 반환됩니다.
>>> getattr(person, 'age', 0)
0
당신은 사용할 수 getattr
와 함께 dir
모든 속성 이름을 반복하고 그 값을 얻을 :
>>> dir(1000)
['__abs__', '__add__', ..., '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
>>> obj = 1000
>>> for attr_name in dir(obj):
... attr_value = getattr(obj, attr_name)
... print(attr_name, attr_value, callable(attr_value))
...
__abs__ <method-wrapper '__abs__' of int object at 0x7f4e927c2f90> True
...
bit_length <built-in method bit_length of int object at 0x7f4e927c2f90> True
...
>>> getattr(1000, 'bit_length')()
10
이에 대한 실제적인 사용은 이름이로 시작하는 모든 방법을 찾을 것 test
과 그들에게 전화를 .
유사에 getattr
가 setattr
당신이 그 이름을 가진 개체의 속성을 설정할 수있는 :
>>> setattr(person, 'name', 'Andrew')
>>> person.name # accessing instance attribute
'Andrew'
>>> Person.name # accessing class attribute
'Victor'
>>>
답변
나 getattr
에게이 방법을 설명하는 것이 가장 쉽습니다.
메소드 이름을 입력하는 대신 문자열 컨텐츠를 기반으로 메소드를 호출 할 수 있습니다.
예를 들어 다음을 수행 할 수 없습니다.
obj = MyObject()
for x in ['foo', 'bar']:
obj.x()
x는 유형이 아니기 때문에 builtin
,하지만 str
. 그러나 다음을 수행 할 수 있습니다.
obj = MyObject()
for x in ['foo', 'bar']:
getattr(obj, x)()
입력을 기반으로 객체와 동적으로 연결할 수 있습니다. 사용자 정의 객체 및 모듈을 다룰 때 유용하다는 것을 알았습니다.
답변
일반적인 사용 사례 getattr
는 데이터를 함수에 매핑하는 것입니다.
예를 들어 Django 나 Pylons와 같은 웹 프레임 워크에서 getattr
에서 웹 요청의 URL을 처리 할 함수에 간단하게 매핑 할 수 있습니다. 예를 들어 Pylons의 라우팅을 살펴보면 최소한 기본적으로 다음과 같이 요청의 URL이 잘리는 것을 볼 수 있습니다.
http://www.example.com/customers/list
“고객”과 “목록”으로. 그런 다음 이름이 지정된 컨트롤러 클래스를 검색합니다.CustomerController
. 클래스를 찾으면 클래스의 인스턴스를 작성한 다음 메소드 getattr
를 얻는 데 사용 합니다 list
. 그런 다음 해당 메소드를 호출하여 요청을 인수로 전달합니다.
이 아이디어를 이해하면 웹 애플리케이션의 기능을 확장하기가 쉽습니다. 컨트롤러 클래스에 새 메소드를 추가 한 다음 해당 메소드에 적합한 URL을 사용하는 페이지에 링크를 작성하십시오. 이 모든 것이 가능합니다 getattr
.
답변
다음은 클래스를 사용하여 실행되는 운영 체제에 따라 클래스가 다른 버전의 저장 메소드를 실행하는 방법에 대한 빠르고 더러운 예입니다 getattr()
.
import os
class Log(object):
def __init__(self):
self.os = os.name
def __getattr__(self, name):
""" look for a 'save' attribute, or just
return whatever attribute was specified """
if name == 'save':
try:
# try to dynamically return a save
# method appropriate for the user's system
return getattr(self, self.os)
except:
# bail and try to return
# a default save method
return getattr(self, '_save')
else:
return getattr(self, name)
# each of these methods could have save logic specific to
# the system on which the script is executed
def posix(self): print 'saving on a posix machine'
def nt(self): print 'saving on an nt machine'
def os2(self): print 'saving on an os2 machine'
def ce(self): print 'saving on a ce machine'
def java(self): print 'saving on a java machine'
def riscos(self): print 'saving on a riscos machine'
def _save(self): print 'saving on an unknown operating system'
def which_os(self): print os.name
이제이 클래스를 예제로 사용하자 :
logger = Log()
# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along
# somewhere else as 1st class:
save_func()
# or you can just call it directly:
logger.save()
# other attributes will hit the else
# statement and still work as expected
logger.which_os()
답변
여기에 모든 놀라운 답변 외에도 사용 방법이 있습니다. getattr
많은 코드 줄을 저장하고 아늑한 상태로 유지하는 데 수 . 이러한 생각은 때때로 필요할 수있는 끔찍한 코드 표현을 따르게되었습니다.
대본
디렉토리 구조가 다음과 같다고 가정하십시오.
- superheroes.py
- properties.py
그리고, 당신은에 대한 정보를 얻기위한 기능을 가지고 Thor
, Iron Man
, Doctor Strange
에 superheroes.py
. 당신은 매우 현명에서 그들 모두의 속성을 적어 properties.py
소형에서 dict
한 다음에 액세스 할 수 있습니다.
properties.py
thor = {
'about': 'Asgardian god of thunder',
'weapon': 'Mjolnir',
'powers': ['invulnerability', 'keen senses', 'vortex breath'], # and many more
}
iron_man = {
'about': 'A wealthy American business magnate, playboy, and ingenious scientist',
'weapon': 'Armor',
'powers': ['intellect', 'armor suit', 'interface with wireless connections', 'money'],
}
doctor_strange = {
'about': ' primary protector of Earth against magical and mystical threats',
'weapon': 'Magic',
'powers': ['magic', 'intellect', 'martial arts'],
}
이제 요청시 각 기능을 반환한다고 가정 해 보겠습니다 superheroes.py
. 따라서 다음과 같은 기능이 있습니다
from .properties import thor, iron_man, doctor_strange
def get_thor_weapon():
return thor['weapon']
def get_iron_man_bio():
return iron_man['about']
def get_thor_powers():
return thor['powers']
… 키와 슈퍼 히어로에 따라 다른 값을 반환하는 더 많은 함수.
의 도움으로 getattr
다음과 같은 작업을 수행 할 수 있습니다.
from . import properties
def get_superhero_weapon(hero):
superhero = getattr(properties, hero)
return superhero['weapon']
def get_superhero_powers(hero):
superhero = getattr(properties, hero)
return superhero['powers']
코드 줄, 함수 및 반복 수를 상당히 줄였습니다!
물론 properties_of_thor
변수 와 같은 나쁜 이름이 있다면 간단히 수행하여 만들거나 액세스 할 수 있습니다
def get_superhero_weapon(hero):
superhero = 'properties_of_{}'.format(hero)
all_properties = getattr(properties, superhero)
return all_properties['weapon']
참고 :이 특정 문제의 경우 상황을 처리하는 더 현명한 방법이있을 수 있지만 getattr
올바른 위치에서보다 깨끗한 코드를 작성 하는 방법에 대한 통찰력을 얻는 것이 좋습니다 .
답변
# getattr
class hithere():
def french(self):
print 'bonjour'
def english(self):
print 'hello'
def german(self):
print 'hallo'
def czech(self):
print 'ahoj'
def noidea(self):
print 'unknown language'
def dispatch(language):
try:
getattr(hithere(),language)()
except:
getattr(hithere(),'noidea')()
# note, do better error handling than this
dispatch('french')
dispatch('english')
dispatch('german')
dispatch('czech')
dispatch('spanish')