При выборе метода должен ли пользователь устанавливать его при создании экземпляра или позже? - PullRequest
0 голосов
/ 05 августа 2020

Я перейду к примеру, так как думаю, он станет более понятным. Должен ли я предпочесть это:

class Substance():

    def __init__(subst,name,density_method,**kwargs):
         
        self.name   = name
        self.kwargs = kwargs
        self.density_method = density_method

    def density_method_1(self):
        #Something Here

    def density_method_2(self):
        #Something Else Here

class Air(Substance):
    Subst.__init__(self,name,gas_density_method=gas_density_method_1,**kwargs)

    # More stuff here

Air_1 = Air('Air_1',T=700,P=101325)
Air_2 = Air('Air_2',gas_density_method=gas_density_method_2,T=700,P=101325)

Или это:

class Substance():

    def __init__(subst,name,**kwargs):
         
        self.name   = name
        self.kwargs = kwargs
        self.density_method = density_method_1 #Default is now here

    def density_method_1(self):
        #Something Here

    def density_method_2(self):
        #Something Else Here

class Air(Substance):
    Subst.__init__(self,name,**kwargs)

    # More stuff here

Air_1 = Air('Air_1',T=700,P=101325)
Air_2 = Air('Air_2',T=700,P=101325)
Air_2.density_method = density_method_2

Это базовый пример c, но у меня есть более 10 методов на подмножество (плотность, вязкость и т. c), и у каждого может быть 1 или несколько различных возможностей. Является ли ответ здесь чисто дизайнерским, есть ли какая-нибудь хорошая «практика», и является ли один из них лучше с точки зрения производительности (что важно в моем случае)? Кроме того, что произойдет, если у density_method_2 есть дополнительные аргументы, чем у method_1? (Поскольку пользователь активно запрашивает метод_2, его долг - знать, что есть дополнительные аргументы, и поэтому я в настоящее время заставляю их передавать через ** kwargs, которые позже будут собраны в соответствующем методе) Заранее спасибо и удачного дня !

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Что касается производительности. Разница действительно сводится к использованию переменной или словаря. В этот момент вы говорите о миллисекундах, это микро-оптимизация, которая имеет очень специализированные варианты использования.

На самом деле нет хорошей «лучшей практики» для этого сценария, поэтому это будет больше зависеть от того, как вы собираетесь используйте методы.

Что касается других методов, имеющих разные переменные, все сводится к тому, когда вы действительно вызываете эти методы. В этом коде вы только устанавливаете их в переменную, чтобы стандартизировать способ их вызова, но на самом деле вы их не вызываете. Чтобы добавить единообразия, я бы сделал дополнительные переменные необязательными. Хотя, опять же, это как бы зависит от того, что вы хотите, чтобы они делали и что вам от них нужно.

Edit: Я неправильно прочитал некоторые из ваших вопросов, поэтому мой ответ не был полностью понятен. Согласно вашему комментарию, я бы посмотрел на это так.

Сначала давайте внесем некоторые изменения в класс Substance:

class Substance():
    # Notice here I changed 'subst' to self. That was just a syntax error
    def __init__(self, name, density_method, **kwargs):
        self.name = name
        self.kwargs = kwargs
    
        # This is where we get into the substance of the method.
        # The density method is going to be what you call as a method later on.
        # For now we just have to initialize it.
        self.density_method = None

        # This will be the setter function to make it so we can use the 
        # different density methods
        # Since there is a call to it in the init function, we can always call it again later
        self.set_density_method(density_method)

Теперь мы должны сделать функцию установки, чтобы вы могли передать различные значения в методе, и он изменит, какой метод плотности вы используете. Вы можете использовать getattr (object, string) как относительно безопасный способ поиска сигнатуры метода. Документация: здесь для getattr ()

    def set_density_method(new_method):
        self.density_method = getattr(self, new_method)

Теперь измените класс Air, чтобы отразить изменения, внесенные вами в родительский класс:

class Air(Substance):
    # The method variable here is the default density class.
    # If you want there to be no default, remove everything to the right of =
    def __init__(self, name, method='density_method_1', **kwargs):
        Substance.__init__(self, name, density_method=method, **kwargs

Так с эти изменения, реализация меняется, но незначительно. подобные вещи, но это выходит за рамки этого вопроса.

Окончательный код:

class Substance():
    def __init__(self, name, density_method, **kwargs):
        self.name = name
        self.kwargs = kwargs
        self.density_method = None
        self.set_density_method(density_method)


    def set_density_method(self, new_method):
        self.density_method = getattr(self, new_method)

    def density_method_1(self):
        # Something Here
        print('density 1')

    def density_method_2(self):
        # Something Else Here
        print('density_2')

    def density_method_3(self):
        # Something Else Here
        print('density_3')


class Air(Substance):
    def __init__(self, name, method='density_method_1', **kwargs):
        Substance.__init__(self, name, density_method=method, **kwargs)


Air_1 = Air('Air_1',T=700,P=101325)
Air_1.density_method()
Air_2 = Air('Air_2',T=700,P=101325)
Air_2.set_density_method('density_method_2')
Air_2.density_method()

Air_3 = Air('Air_3', method='density_method_3', T=700, P=101325)
Air_3.density_method()

print('wait')
1 голос
/ 05 августа 2020

Всегда лучше внедрить зависимости. В этом случае ваш первый вариант лучше. Это делает ваш код более тестируемым и легким для имитации. Попробуйте написать тесты для обоих случаев, и вы поймете, почему. Узнайте больше о внедрении зависимостей и утином вводе с помощью Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...