Когда атрибут зависит от 2 классов, в каком классе он должен быть определен?

#python #oop

#python #ооп

Вопрос:

Допустим, у меня есть 2 класса: Water и Substance . один или несколько Substance s могут быть растворены в Water ; у Water экземпляра есть substances атрибут, содержащий список Substance экземпляров. Константа диффузии a Substance зависит от атрибутов Water , в которых он растворен, а также от некоторых атрибутов Substance самого. Должен ли я затем создать get_diffusion_constant метод на Water с экземпляром Substance в качестве атрибута, или я должен добавить метод в, Substance где Water его аргумент? Или есть совсем другой подход?

Комментарии:

1. Вы написали «Константа диффузии вещества», что означает, что константа диффузии является атрибутом вещества. Таким образом, get_diffusion_constant должен быть метод Substance

2. да, это допустимый аргумент. Я подумал то же самое. Но теперь, когда у меня есть другой метод, Water который вычисляет некоторое свойство вещества, зависящее от константы диффузии, я пишу: self.substances[0].get_diffusion_constant(self) . Особенно self в качестве аргумента кажется мне странным

3. Использование self в качестве аргумента меня не беспокоит. Это просто ссылка на Water экземпляр, как и на любой другой Water экземпляр. self Имя аргумента — это просто соглашение, которое, к счастью, используется всеми. Но технически в нем нет ничего особенного; вы могли бы определить свои методы с помощью this (или foo , или чего-либо еще) в качестве первого параметра и использовать this (или foo , или что-нибудь еще) в качестве текущего экземпляра, это также сработало бы.

4. Я не уверен, как это вписывается в общий дизайн вашей системы, но другим вариантом является класс DiffusionConstant, который использует воду (и вещества?) в качестве аргументов конструктора. Он может либо выполнять вычисление как часть конструктора, либо как метод (возможно, с именем value).

5. @Tryph да, спасибо за заверение, что это нормальное кодирование. Я оставлю это таким образом. Вы могли бы сделать из этого ответ, и я приму его.

Ответ №1:

Вы написали:

Константа распространения Substance зависит от атрибутов Water

Это позволяет думать, что константа диффузии является характеристикой вещества, поэтому Substance классу должен принадлежать метод, позволяющий его вычислять (с параметром для предоставления Water экземпляра, поскольку это зависит от него).

Это хорошо работает для самого простого случая, если real concepts владеет характеристикой, его модели (в данном случае классу) должен принадлежать соответствующий атрибут или метод.

Некоторые шаблоны проектирования и / или более сложные потребности могут оправдать нарушение этого «правила» для введения большего ограничения.


Кроме того, чтобы ответить на ваш комментарий: передача self функции не является проблемой (по крайней мере, IMO). self это просто ссылка на текущий экземпляр и ничего особенного, за исключением того, что это широко уважаемое соглашение об именовании текущего экземпляра и, следовательно, первого аргумента методов (экземпляра).

Чтобы объяснить немного больше: метод экземпляра должен принимать в качестве первого аргумента ссылку на связанный экземпляр. По соглашению, этот позиционный аргумент называется self , но вы могли бы назвать его this , instance или как угодно, это было бы то же самое. Тогда вам просто нужно будет использовать правильное имя параметра внутри метода.

Смотрите код ниже. Он использует очень плохие имена для аргумента экземпляра, но он работает так, как если бы self использовался:

 class Foo:
    def __init__(current_instance):
        current_instance.bar = 'baz'

    def __str__(this_name_is_ridiculous):
        return this_name_is_ridiculous.bar


print(Foo())  # prints baz
  

Ответ №2:

Я предполагаю, что это Water наследует некоторые вещи от Substance . Таким образом, у вас может быть diffusion_constant в каждом Substance , а также diffuse функция, которая принимает один или несколько Substance с

Редактировать:

 class Water:
     def diffuse(self, *args):
         #check if args is greater 0 or None and then iterate and apply diffusion_constants

class Substance:
      diffusion_constant = 0 #base constant

class Sirup(Substance):
      diffusion_constant = 3

#somewhere later then
corn_sirup = Sirup()
sugary_sirup = Sirup()
water = Water()
water.diffuse(corn_sirup, sugary_sirup)
  

Редактировать:
Из-за комментария я изменил код. В Python есть утиный ввод, поэтому, пока ваши вещества имеют diffusion_constant атрибут, к нему можно получить доступ, независимо от того, что это такое. Тогда это должно сработать

Комментарии:

1. Извините, вода не наследуется от вещества. Я вижу путаницу, поскольку вода в некотором смысле является веществом. Но вещества в моем случае относятся к веществам, растворенным в воде