2017-03-17 5 views
3

numpy을 사용하는 경우 코드에 np.*이 많이 있습니다.numpy 수식의 일시적인 와일드 카드 가져 오기/가독성

import numpy as np 
y = np.sin(np.abs(np.linspace(0, 2*np.pi))) 

이것은 수식을 어수선하게 만들고 덜 읽을 수있게합니다. 와일드 카드 가져 오기를 사용하여이 문제를 해결할 수 있습니다.

from numpy import * 
y = sin(abs(linspace(0, 2*pi))) 

그러나 와일드 카드 가져 오기는 거의 항상 나쁜 아이디어입니다.

수식 (또는 수학 코드 블록)으로 제한된 컨텍스트에 와일드 카드 가져 오기를 할 수 있는지 궁금합니다. 이렇게하면 가독성이 유지되고 네임 스페이스 오염이 더 쉽게 제어 할 수있는 작은 코드 영역으로 제한됩니다.

with import_wildcard(numpy): 
    y2 = sin(abs(linspace(0, 2*pi))) 

질문 :

  1. 이 허용하는 몇 가지 언어 구조가 거기에 내가 이런 일을하고 싶습니다.
  2. 요청 자체가 합리적입니까, 아니면 잠재적 인 문제점을 간과합니까?
+1

와일드 카드를 스코프에 임포트하면,'SyntaxWarning : import *는 모듈 레벨에서만 허용됩니다'. –

+0

'from numpy import sin, abs, linespace, pi' – erip

+2

접두어가 붙은'np.'가 일을 덜 읽을 수 있다는 것에 동의하지 않습니다. 사실, 나는 반대로 말하고 싶습니다. 독자는 어디에서 'abs'가 왔는지 확인할 필요가 없습니다. 'np.abs' 또는'builtins.abs'입니까? – erip

답변

1

해결 방법 2 : 일시적으로 지정된 객체 피드백을 바탕으로

을 촉진, 여기에 더 명시 또 다른 방법입니다. 임시 와일드 카드 가져 오기를 만드는 대신 지정된 개체 만 전역 네임 스페이스에 일시적으로 승격합니다.

class global_context(object): 
    def __init__(self, *objects): 
     """Return a context manager that has the given objects available in the global namespace. 

     You can directly pass in an object if it has a __name__, otherwise use the string name. 
     """ 
     def parse_object(obj): 
      if isinstance(obj, str): 
       ns, name = obj.split('.') 
       return name, getattr(globals()[ns], name) 
      else: 
       return obj.__name__, obj 
     self.identifiers = dict(parse_object(o) for o in objects) 
     self.globals_backup = {} 

    def __enter__(self): 
     _globals = globals() 
     for name, fn in self.identifiers.items(): 
      if name in _globals: 
       self.globals_backup[name] = _globals[name] 
     _globals.update(self.identifiers) 

    def __exit__(self, exc_type, exc_value, exc_tb): 
     _globals = globals() 
     for name in self.identifiers: 
      if name not in self.globals_backup: 
       del _globals[name] 
     _globals.update(self.globals_backup) 
     self.globals_backup.clear() 

사용법 :

import numpy as np 
with global_context(np.sin, np.abs, np.linspace, 'np.pi'): 
    y = sin(abs(linspace(0, 2*pi))) 

내가 처음 솔루션을 떠날거야뿐만 아니라 각 방법의 장점과 단점이 더 쉽게 논의 될 수 있도록, 사람들이 각각의 솔루션을 투표 할 수 있습니다.

2

해결 방법 1 : 임시 와일드 카드 가져 오기 :
class import_wildcard(object): 
    """Contextmanager to temporary import a package content into the global namespace.""" 
    def __init__(self, packagename): 
     self.packagename = packagename 
     self.package = __import__(self.packagename, globals(), locals()) 
     self.globals_backup = {} 

    def __enter__(self): 
     _globals = globals() 
     for name in self.package.__dict__: 
      if name in _globals: 
       self.globals_backup[name] = _globals[name] 
     _globals.update(self.package.__dict__) 

    def __exit__(self, exc_type, exc_value, exc_tb): 
     _globals = globals() 
     for name in self.package.__dict__: 
      if name not in self.globals_backup: 
       del _globals[name] 
     _globals.update(self.globals_backup) 
     self.globals_backup.clear() 


with import_wildcard('numpy'): 
    y = sin(abs(linspace(0, 2*pi))) 

는 지금까지 내가 큰 단점 건너 적이 없다. numpy의 일부 함수와 같은 이름의 컨텍스트 외부에서 정의 된 코스 변수는 문맥에서 액세스 할 수 없습니다.