2010-08-09 3 views
1

필자는 텍스트 파일을 파싱하고, 텍스트에서 만나는 다양한 개체에 대한 개체를 만들고, 추가 처리를 위해 데이터 구조 (예 : 목록)에 넣어야합니다. 텍스트의 예 :문자열을 통해 클래스 이름을 참조 하시겠습니까?

laptop 
17" dell, weight: 12 lb 
desktop 
24" hp 

나는 실체가 텍스트에 존재할 수있는 사전에 알고, 어떤 속성 것은 그들이 가지고로되어있다. 이 예제에서는 클래스 랩톱과 데스크톱 (이미 클래스 컴퓨터의 하위 클래스)을 정의했습니다. 파서는 객체 랩톱 ('dell', 17, 12)과 dekstop ('hp', 24)을 생성하기 만하면됩니다.

이 경로를 따르면 문자열에서 클래스 이름을 검색하고 해당 클래스의 개체를 만들어야합니다. 그것은 일을하는 Pythonic 방식입니까? 그렇다면 가장 좋은 접근 방법은 무엇입니까 (Python 3.1 사용)? 그렇지 않다면 대신 무엇을해야합니까?

감사합니다.

무엇

답변

11

입니다

은, 말하자면, 당신이 할 수있는 다음 코드

obj = globals()[classname]() 
를 사용하여 그것의 이름으로 클래스의 인스턴스를 만들 수 있습니다

import computers 
getattr(computers, "Laptop")(<params>) 

computers.Laptop. 그들은 당신이 (그들은 전역 변수가 너무)에서 코드를 실행하는 동일한 파일에 정의되어있는 경우, 당신은

globals()[ "Laptop" ] 

그러나이 덜 우아 할 수 있습니다; 별도의 범위에 넣는 것이 더 좋을 것입니다.

또는 "Nettop", "Lapbook"및 "Laptop"에서 모두 Laptop을 인스턴스화하려는 경우보다 강력한 매핑을 원할 경우 문자열을 해당 생성자에 매핑하여 유지 관리 할 수 ​​있습니다.

mapping = { "Laptop": Laptop, "Nettop": Laptop, ... } 
mapping[ "Laptop" ]() 
+0

+1 맵핑 접근 방식이 바람직하다고 생각합니다. – PaulMcG

0
파이썬 코드의 구문에 대한 확인

하지 그러나 이것은 당신이 원하는 무엇?

for item in parsedString: 
    if item == "laptop": 
     laptops.add(laptop()) #laptops is a list of laptops you 
           #have encountered so far in your list 
    # add the next elements to your laptop instance 

    if item == "desktop": 
    # code for desktop... 
+0

은 가정하자 나는 수업의 수십, 그리고 파서 모듈도 반드시 그들 모두의 인식하지 못합니다. 필자는 객체의 유형을 문자열 변수로 구문 분석하고 파서가 관련 클래스의 객체를 생성하도록합니다. – max

+0

@katrielalex가 그 대답이라고 생각합니다 – Rahul

5

당신은 classname이 클래스가 computers.py에 정의되어있는 경우 문자열

+0

이것은 파이썬으로 간주됩니까? – max

+0

그것이 실패하면 고통이 될 것이므로 그것은 분명히 당신이 가볍게해야하는 것은 아닙니다. 그러나 전역 네임 스페이스에서 무언가를 절대적으로 액세스해야한다면, 이것은 다른 모든 네임 스페이스에 대해 getattr/setattr이있는 방법입니다. – delnan

4

기술적으로, 당신은 단지 아주 좋은 방법이 아닙니다 (또는 적어도 방식 모두가 그것을 해석한다)을 요구하는지 당신이 신뢰할 수없는 소스로부터 입력을 복용 할 수있다 특히 (모든 소스를 기억 자신 이외의 사람는 일반적으로 신뢰할 수없는 것으로 간주됩니다!). 누군가가 당신이 정말로 원하지 않는 속성으로 의도하지 않은 객체의 생성이나 함수의 실행을 트리거 할 수 있기 때문에 이러한 것들을 명시 적으로 화이트리스트해야합니다 ...

대신 할 수있는 것은 다음과 같습니다 (이 격렬 불완전 물론이지만, 당신에게 일반적인 아이디어를 줄 것이다) :

class Laptop(object): 
    pass 
class Desktop(object): 
    pass 

possible_classes = { 
    "laptop": Laptop, 
    "desktop": Desktop, 
} 

new_object = possible_classes[identifier_string](propA, propB, propC, ...) 

그런 다음 바로 possible_classes의 DICT에 객체의 각각의 새로운 종류의 매핑을 추가합니다.

+0

+1 보안 문제 – katrielalex

1

나는 검사 기반 방법이 잠재적으로 매우 약해서 변화에 저항 할 수 있다고 생각합니다. 다른 모듈의 클래스를 사용하려면 어떻게해야할까요?

왜 개체 팩토리가 아닌가요? 그것은 단순한 함수 또는 클래스 일 수 있습니다.

예 :

class ComputerFactory: 

    def __init__(self): 
     self._classes = {} 

    def register(moniker, creator): 
     """Moniker is a name for the class. 
     Creator is a callable that creates the object 
     for the moniker. 
     """ 
     self._classes[moniker] = creator 

    def create(moniker, *args, **kwargs): 
     return self._classes[moniker](*args, **kwargs) 

# Example usage 
fac = ComputerFactory() 
# Register constructor 
fac.register("laptop", Laptop) # Laptop class is also a callable (the constructor) 
# Register construction proxy 
def sony_laptop_builder(make): 
    return Laptop("Sony") 
fac.register("laptop", sony_laptop_builder) 
관련 문제