Подтвердить что ты не робот

Динамический выбор класса для наследования

Знания My Python ограничены, мне нужна помощь в следующей ситуации.

Предположим, что у меня есть два класса A и B, можно ли сделать что-то вроде следующего (концептуально) в Python:

import os
if os.name == 'nt':
    class newClass(A):
       # class body
else:
   class newClass(B):
       # class body

Итак, проблема в том, что я хотел бы создать класс newClass, чтобы он наследовал от разных базовых классов на основе разницы в платформе, возможно ли это сделать в Python? Спасибо.

4b9b3361

Ответ 1

Вы можете использовать условное выражение :

class newClass(A if os.name == 'nt' else B):
    ...

Ответ 2

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

class _newClassNT(A):
    # class body

class _newClassOther(B):
    # class body

newClass = _newClassNT if os.name == 'nt' else _newClassOther

Это предполагает, что вам нужно действительно выполнять разные действия в рамках класса. Если вам нужно только изменить наследование, вы можете просто вставить оператор if:

class newClass(A if os.name == 'nt' else B):
    # class body

Ответ 3

Исходя из миров Java и С#, мысль о том, чтобы делать что-то подобное, делает меня cringe = P. (Не то, что идея условного наследования класса плоха - я просто не привык к этому.)

Размышляя об этом немного, я бы сделал что-то подобное, если бы этот вопрос касался Java. Я отправляю шаблон - реализую интерфейс, затем использую factory для выбора между реализациями - чтобы обеспечить еще одну перспективу проблемы:

public interface OsDependent {
  public void doOsDependentStuff();
}

public class WindowsDependentComponent implements OsDependent {
  @Override
  public void doOsDependentStuff() {
    //snip
  }
}

public class AppleDependentComponent implements OsDependent {
  @Override
  public void doOsDependentStuff() {
    //snip
  }
}

public class OsDependentComponentFactory {
  public OsDependent getOsDependentComponent(Platform platform) {
    if(platform == Platform.WINDOWS)
      return new WindowsDependentComponent();
    else if(platform == Platform.APPLE)
      return new AppleDependentComponent();
    else
      return null;
  }
}

Определенно намного больше кода, но это подходящее решение в строго типизированной среде.


EDIT: Одна существенная разница, которую я заметил между моим ответом и оригинальным вопросом:

Если вы условно наследуете от нескольких разных классов, то суперклассы содержат код, который зависит от используемой ОС, в то время как класс, который наследует от них, содержит код, который является одинаковым для всех ОС. Верхняя цепочка наследования зависит от ОС; внизу нет.

Мой подход идет другим путем. Интерфейс OsDepndent (или суперкласс) определяет методы, похожие для всех платформ, в то время как разные реализации (или подклассы) имеют код, зависящий от ОС. Верхняя цепочка наследования является OS-агностиком.

Ответ 4

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

class A():
    # Class A Body
class B():
    # Class B Body
class C():
    # Class C Body
class D():
    # Class D Body
def MakeObject(InheritedClassName): # InheritedClassName is a string
    def CheckClass(InheritedClass):
        if InheritedClass == "A":
            return A
        elif InheritedClass == "B":
            return B
        elif InheritedClass == "C":
            return C
        else:
            return D
    class WantedClass(CheckClass(InheritedClassName)):
        # WantedClass Body
    YourObject = WantedClass()
    return YourObject
CreateObject = MakeObject(str(input("Chose A, B, C or D")))

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

Ответ 5

Для тех, кто имеет схожие потребности, работая с разными модулями. Сначала создайте файл switcher.py и вставьте в него

class Switcher():
    def choose(clname):
         Switcher.clname = clname

Далее, в newClass.py поставьте

import switcher

class newClass(switcher.Switcher.clname):
    ...

Наконец, в вашем главном script

import switcher
import os
    if os.name == 'nt':
        switcher.Switcher.choose(A):
    else:
        switcher.Switcher.choose(B):

# that the moment you're creating class with desired inheritance
import newClass.newClass