Mam obowiązującą aplikację Pythona (Python V2.7), która importuje zewnętrzne pliki PY w locie, która zawiera specjalnie o nazwie klas, aby przetwarzać dane. Załadowany plik PY PY jest wybierany na podstawie rodzaju po przetwarzania potrzebnych danych.

Więc mam tę kolekcję klas, każdy we własnym dokumencie. Pliki są nazwane w określonej modzie w oparciu o rodzaj przetwarzania, dzięki czemu główny program wie, jakiego pliku do zaimportowania z żądania upstream.

Należy

Chciałbym zaimportować "szablon" wspólnych funkcji w zakresie klasy, które mogą dostarczyć standardowy zestaw elementów sterujących, których oczekuje, nie ma potrzeby kopiowania / wklejania ich do każdego pliku. Nienawidzę tego, gdy znajdę błąd i dokonuję korekcji w jednej z tych głównych funkcji I / O, które następnie muszą replikować od trzydziestu kilku innych plików.

Teraz rozumiem od Googling, że mój import tutaj jest zły ... Otrzymuję wiadomość:

TestClassFile.py:5: SyntaxWarning: import * only allowed at module level

Ale ta metoda jest jedynym sposobem, w jaki znalazłem importowanie funkcji, aby wchodzą do przestrzeni nazw samej klasy. Mam przykład poniżej ...

Jaka metoda (jeśli istnieje) jest odpowiednim sposobem na to w Pythonie?

Przykład

Main.py

import TestClassFile
print "New TestClass - Init"
oTest = TestClassFile.TestClass("foo")

print "Should run...  Function A"
oTest.funcA()

print "Should run...  Function b"
oTest.funcB()

TestClassFile.py.

class TestClass:

    from TestClassImport import *

    def __init__(self, str):
        print "INIT! and be ... ", str

    def funcA(self):
        print "Function A"

Testclassimport.py.

def funcB(self):
    print "Function B"

Bardzo doceniany!


Aktualizuj

Wielkie podziękowania dla wszystkich za wkłady. Od badania miksów wydają się one być właściwym sposobem, aby przedłużyć klasę.

Testclassimport.py.

class ImportClass:
    def funcB(self):
        print "Function B"

TestClassFile.py.

from TestClassImport import ImportClass
class TestClass(ImportClass):

    def __init__(self, str):
        print "INIT! and be ... ", str

    def funcA(self):
        print "Function A"
4
Peter B 24 czerwiec 2017, 00:44

4 odpowiedzi

Najlepsza odpowiedź

Brzmi to tak, jak powinieneś wykonać importowane funkcje w miksinach, z których można dziedziczyć. Więc:

Testclassimport.py.

class ClassB(object):
    def funcB(self):
        print "Function B"

TestClassFile.py.

from TestClassImport import ClassB
from OtherClassImport import ClassX

class TestClass(ClassB, ClassX):
    ...
3
Daniel Roseman 23 czerwiec 2017, 21:53

Możesz użyć importu dla tego, np.:

import importlib


class TestClass:
    def __init__(self, module_name):
        _tmp = importlib.import_module(module_name)
        for elem in _tmp.__dir__():
            if not elem.startswith('_'):
                prop = getattr(_tmp, elem)
                setattr(self, elem, prop)
    def funcA(self):
        print("function A")

tc = TestClass('some_module')
tc.funcB()
>>> prints "function B"

W tym podejściu możesz utworzyć funkcję load_module(module_name) zamiast __init__(), aby załadować moduły niezależnie od siebie (np. Zapobieganie kolizji nazw).

0
Bogusław Kałka 23 czerwiec 2017, 22:29

Nie wiem, czy jest to w żaden sposób jest to rozwiązanie , ale można napisać funkcję, aby skonstruować metaklas, aby dynamicznie dodać właściwości do swoich klas.

def make_meta(*import_classes):
    class TestMeta(type):
        def __new__(meta, name, bases, dct):
            new_class = super(TestMeta, meta).__new__(meta, name, bases, dct)
            for import_class in import_classes:
                for name in vars(import_class):
                    if not name.startswith('__'):
                        prop = getattr(import_class, name)
                        setattr(new_class, name, prop)
            return new_class
    return TestMeta


class TestClass:

    import TestClassImport
    __metaclass__ = make_meta(TestClassImport)

    # other functions defined as normal...

Dodaje to wszystko w globalnym zakresie testuSclassimport.py, który nie zaczyna się od "__" jako nieruchomość na TestClass.

Lub można użyć dekoratora klasy dynamicznie dodawać właściwości w tej samej modzie.

def add_imports(*import_classes):
    def augment_class(cls):
        for import_class in import_classes:
            for name in vars(import_class):
                if not name.startswith('__'):
                    prop = getattr(import_class, name)
                    setattr(cls, name, prop)
            return cls
    return augment_class


import TestClassImport

@add_imports(TestClassImport)
class TestClass:
    # normal class body

Ale Mixins wydają się lepsze podejście.

0
Jared Goguen 23 czerwiec 2017, 22:16

To wydaje się działać:

import types

from TestClassImport import funcB

class TestClass:

    def __init__(self, str):
        print "INIT! and be ... ", str
        setattr(self, 'funcB', types.MethodType(funcB, self, TestClass))

    def funcA(self):
        print "Function A"

Po uruchomieniu otrzymuję następujący wynik:

INIT! and be ...  foo
Should run...  Function A
Function A
Should run...  Function b
Function B
0
ngoldbaum 23 czerwiec 2017, 21:55