2013-02-27 3 views
2

필자가 본 내장 클래스와 다른 "성숙한"파이썬 구성 요소처럼 작동하는 클래스를 작성하려고합니다. 나의 Pythonic 교육은 학급별로 조금 여드름이 많다. 나는 그것이 모두 섞여서 걱정된다.모듈 구성, ​​상속 및 @classmethods

처리되지 않은 파일 (및 해당 이름) 사전과 처리 된 파일 (및 해당 이름) 사전을 포함하는 일종의 저장소 역할을하는 클래스를 만들고 싶습니다. 파일을 열고 처리하는 것과 같은 일을 처리하는 다른 하위 클래스를 구현하고 싶습니다. 파일 처리 클래스는 기본 클래스의 사전을 업데이트 할 수 있어야합니다. 내가 직접 개별적으로 예를 들어 모든 것을 인스턴스화 할 필요없이 다양한 서브 모듈을 호출 할 수 싶습니다

import Pythia 
p = Pythia() 
p.FileManager.addFile("/path/to/some/file") 

또는

Pythia.FileManager.addFile("/path/to/some/file") 

내가 물건에 주위를 찾고 있었어요 약 @classmethodsuper 등이 있지만 전적으로 그것을 이해한다고 말할 수는 없습니다. 저는 또한 제가 상속의 전적인 사슬을 가지고 있을지도 모른다고 의심하기 시작했습니다. 제가 생각하기에 제 메인 클래스는 실제로 처리 클래스의 하위 클래스 여야합니다. 또한이 모든 것이 패키지로 더 잘 작동하는지 궁금하지만, 이는 별개의, 매우 협박적인 문제입니다.

여기 내 코드는 지금까지의 :

#!/usr/bin/python 

import re 
import os 
class Pythia(object): 
    def __init__(self): 
     self.raw_files = {} 
     self.parsed_files = {} 
     self.FileManger = FileManager() 
    def listf(self,fname,f): 
     if fname in self.raw_files.keys(): 
      _isRaw = "raw" 
     elif fname in self.parsed_files.keys(): 
      _isRaw = "parsed" 
     else: 
      return "Error: invalid file" 
     print "{} ({}):{}...".format(fname,_isRaw,f[:100]) 

    def listRaw(self,n=None): 
     max = n or len(self.raw_files.items()) 
     for item in self.raw_files.items()[:max]: 
      listf(item[0],item[1]) 

    def listParsed(self,n=None): 
     max = n or len(self.parsed_files.items()) 
     for item in self.parsed_files.items()[:max]: 
      listf(item[0],item[1]) 

class FileManager(Pythia): 
    def __init__(self): 
     pass 
    def addFile(self,f,name=None,recurse=True,*args): 
     if name: 
      fname = name 
     else: 
      fname = ".".join(os.path.basename(f).split(".")[:-1]) 
     if os.path.exists(f): 
      if not os.path.isdir(f): 
       with open(f) as fil: 
        Pythia.raw_files[fname] = fil.read() 
      else: 
       print "{} seems to be a directory.".format(f) 
       if recurse == False: 
        return "Stopping..." 
       elif recurse == True: 
        print "Recursively navingating directory {}".format(f) 
        addFiles(dir,*args) 
       else: 
        recurse = raw_input("Recursively navigate through directory {}? (Y/n)".format(f)) 
        if recurse[0].lower() == "n": 
         return "Stopping..." 
        else: 
         addFiles(dir,*args) 
     else: 
      print "Error: file or directory not found at {}".format(f) 
    def addFiles(self,directory=None,*args): 
     if directory: 
      self._recursivelyOpen(directory) 
     def argHandler(arg): 
      if isinstance(arg,str): 
       self._recursivelyOpen(arg) 
      elif isinstance(arg,tuple): 
       self.addFile(arg[0],arg[1]) 
      else: 
       print "Warning: {} is not a valid argument...skipping..." 
       pass 
     for arg in args: 
      if not isinstance(arg,(str,dict)): 
       if len(arg) > 2: 
        for subArg in arg: 
         argHandler(subArg) 
       else: 
        argHandler(arg) 
      elif isinstance(arg,dict): 
       for item in arg.items(): 
        argHandler(item) 
      else: 
       argHandler(arg) 
    def _recursivelyOpen(self,f): 
     if os.path.isdir(f): 
      l = [os.path.join(f,x) for x in os.listdir(f) if x[0] != "."] 
      for x in l: 
       _recursivelyOpen(x) 
     else: 
      addFile(f) 
+1

'Pythia 가져 오기'는 모듈이 아닌 클래스입니다. 그래서 당신은'피티 아 (Pythia)'를 할 수 없습니다. Pythia라는 이름의 모듈에서 Pythia라는 클래스를 가질 수 있습니다.이 경우 Pythia.Pythia()를 할 수 있습니다. 그러나 모듈을 pythia라고 부름으로써 혼란을 피하는 것이 더 낫습니다 (PEP8이 암시 하듯이). – abarnert

+2

한 가지 더 :'self.FileManger = FileManager()'는 정말 나쁜 생각입니다. 그 클래스의 클래스와 인스턴스의 이름을 지정하면 똑같은 것이 혼란을 가져올 수 있습니다. (Eevee가 제안한대로 PEP8을 따르는 경우, 결코'file_manager'는 일반적인'FileManager' 인스턴스에 대한 합리적인 이름입니다. 그러나 그렇지 않다면, Apple과 같은 이름을 짓기위한 다른 스타일이 필요합니다. 스타일'aFileManager'). – abarnert

답변

2

첫째는 : PEP8의 지침을 따르십시오. 모듈 이름, 변수 이름 및 함수 이름은 lowercase_with_underscores이어야합니다. 클래스 이름은 CamelCase이어야합니다. 귀하의 코드를 따르는 것은 그렇지 않으면 약간 어렵습니다. :)

당신은 하위 클래스의 인스턴스를 포함하고있는 부모 클래스를 가지고 있습니다.

FileManager은 대체로 수정이나 확장을 사용하여 Pythia의 기능을 수행합니까? 두 가지가 함께 작동한다는 것을 감안할 때 나는 그렇지 않을 것이라고 생각합니다.

나는 당신이 궁극적으로 어떻게 보이길 원하는지 잘 모르겠지만, 상속이 필요 없다고 생각합니다. FileManager은 자체 클래스 일 수 있으며 Pythia 인스턴스에있는 self.file_managerFileManager의 인스턴스가 될 수 있으며, 필요하면 Pythia이 인스턴스에 위임 할 수 있습니다. 이미이 코드를 사용하는 방법과 거리가 멀지 않습니다.

작고 독립적 인 부품을 조립하려면 다음에 서로 끼워 넣는 방법에 대해 걱정하십시오 (). 또한


, 몇 가지 버그와 스타일의 니트 : 당신은 _recursivelyOpen(x)를 호출하지만 self.를 잊어

  • .

  • 쉼표 다음의 단일 공백.

  • 변수 이름으로 max 조심해 : 그것은 또한 내장 함수의 이름입니다.

  • 도움이 될 경우 유형 확인 (isinstance)을 피하십시오.인수 유형에 따라 수십 가지 다른 작업을 수행 할 때 코드를 따르는 것이 매우 어렵습니다. 매우 명확한 인수 유형을 가지며 필요한 경우 다른 인수를 허용하는 도우미 함수를 작성하십시오.

  • 당신은 FileManager 내부 Pythia.raw_files[fname] 가지고 있지만, Pythia는 클래스이며,이 raw_files 어쨌든 속성이 없습니다.

  • recurseTrue, 다음으로 False 인 경우 확인하십시오. 다른 것이 언제입니까? 또한 == 대신 is을 사용하여 이와 같은 기본 싱글 톤을 테스트해야합니다.

+1

+1, 여전히 큰 문제가 빠져있다 : 그는''Pythia''를,''Pythia ('')를하고있다. 나는 그가 Pythia import Pythia를 Pythia 대신에 Pythia를 찾고 있는지, Pythia를 Pythia로 두지 않고 Pythia를 찾았는지 확신하지 못한다. 당신의 제안은 구별을 분명히 할 것이다. 저쪽 편. – abarnert

+0

pff, 그렇습니다. 나는 그것이 실제로 실행하려고 시도한 실제 코드가 아니라고 생각합니다. – Eevee

+0

예, 그는 그가 실행할 수 있기를 원하는 코드라고 말합니다. 그리고 그 단락을 읽으면 모듈과 클래스를 훨씬 더 뒤섞어 쓰는 것 같습니다 (예를 들어 하위 모듈로 'FileManager'를 참조). – abarnert

0

여기에 많은 내용이 있으며 더 많이 배우는 것이 가장 좋습니다. 의도 사용에 대한

:

import Pythia 
p = Pythia() 
p.file_manager.addFile("/path/to/some/file") 

이 같은 클래스 구조가 작동합니다 :

class FileManager(object): 
    def __init__(self, parent): 
     self.parent = parent 

    def addFile(self, file): 
     # Your code 
     self.parent.raw_files[file] = file 

    def addFiles(self, files) 
     # Your code 
     for file in files: 
      self.parent.raw_files[file] = file 

class Pythia(object): 
    def __init__(self): 
     self.file_manager = FileManager(self) 

그러나 선택의 여지가 있습니다. 원하는 코드를 먼저 작성한 다음 클래스/객체를 구현하여이를 구현해야합니다. 파이썬에서 상속을 사용하는 경향이 없으며, 비단뱀 오리 입력으로 인해 실제로 필요하지 않습니다.

또한 클래스를 인스턴스화하지 않고 메서드를 호출하려면 classmethod가 아닌 staticmethod를 사용하십시오. 예 :

class FileManager(object): 
    @staticmethod 
    def addFiles(files): 
     pass 
+1

10 번 중 9 번,'@ staticmethod'는 단지 모듈 수준의 함수 여야합니다. – Eevee

+1

@ Eevee : +1. 정확하게. 초보자들 (특히 최근의 자바 이민자들)에게 가장 좋은 방법은 : 대체 생성자에'@classmethod'를 사용하십시오; '@ staticmethod'를 사용하지 마십시오. 결국에는 예외를 배우지 만 실제로 작동하는 방법을 정확히 배우기 전까지 엄지 손가락 규칙만으로 충분합니다. – abarnert