programing

파이썬에서 다른 클래스 내에서 클래스를 정의하면 이점이 있습니까?

megabox 2023. 7. 23. 14:10
반응형

파이썬에서 다른 클래스 내에서 클래스를 정의하면 이점이 있습니까?

제가 여기서 말하는 것은 중첩된 클래스입니다.기본적으로, 저는 두 개의 수업을 모델링하고 있습니다.Download Manager 클래스 및 다운로드스레드 클래스.여기서 분명한 OOP 개념은 구성입니다.하지만, 구성이 꼭 둥지를 짓는 것을 의미하는 것은 아닙니다, 그렇죠?

다음과 같은 코드가 있습니다.

class DownloadThread:
    def foo(self):
        pass

class DownloadManager():
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadThread())

하지만 지금은 둥지를 틀면 더 좋은 상황이 생길지 궁금해요.다음과 같은 것:

class DownloadManager():
    class DownloadThread:
        def foo(self):
            pass
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadManager.DownloadThread())

이 작업은 "내부" 클래스가 일회성인 경우 수행할 수 있으며, 외부 클래스의 정의 밖에서는 절대 사용되지 않습니다.예를 들어, 메타 클래스를 사용하는 것은 때때로 편리합니다.

class Foo(object):
    class __metaclass__(type):
        .... 

메타 클래스를 한 번만 사용하는 경우 별도로 정의하는 대신 사용할 수 있습니다.

이렇게 중첩된 클래스를 사용한 적이 있는 경우에는 외부 클래스를 네임스페이스로만 사용하여 여러 개의 밀접한 관련이 있는 클래스를 그룹화했습니다.

class Group(object):
    class cls1(object):
       ...

    class cls2(object):
       ...

그런 다음 다른 모듈에서 Group을 가져와 Group.cls1, Group.cls2 등으로 나타낼 수 있습니다.그러나 모듈을 사용하여 동일한 작업을 수행할 수 있다고 주장할 수도 있습니다(아마도 덜 혼란스러운 방법으로).

저는 파이썬을 모르지만, 당신의 질문은 매우 일반적인 것 같습니다.Python에만 해당되면 무시합니다.

클래스 중첩은 범위에 대한 모든 것입니다.한 클래스가 다른 클래스의 맥락에서만 의미가 있다고 생각하면 전자가 내포된 클래스가 되기에 적합한 후보일 수 있습니다.

도우미 클래스를 비공개 중첩 클래스로 만드는 것이 일반적인 패턴입니다.

향상된 기능이 특정 중첩 클래스에 캡슐화된 상속된 클래스를 구성하려는 경우 중첩 클래스에 대한 또 다른 사용법이 있습니다.

다음 예를 참조하십시오.

class foo:

  class bar:
    ...  # functionalities of a specific sub-feature of foo

  def __init__(self):
    self.a = self.bar()
    ...

  ...  # other features of foo


class foo2(foo):

  class bar(foo.bar):
    ... # enhanced functionalities for this specific feature

  def __init__(self):
    foo.__init__(self)

다음의 생성자에서 참고하십시오.foo전선self.a = self.bar()를 구성할 것입니다.foo.bar구성 중인 객체가 실제로foo목적어, 그리고 afoo2.bar생성 중인 객체가 실제로 a일 때 객체foo2물건.

만약 수업이bar클래스 외부에서 정의되었습니다.foo대신, 상속된 버전뿐만 아니라 (이를 호출할 것입니다.bar2예를 들어, 새 클래스 정의foo2훨씬 더 고통스러울 것이다, 왜냐하면 건설자는.foo2 번째 을 첫번줄다로대체합야니해다음으을째합으로 대체해야 .self.a = bar2()전체 생성자를 다시 쓰는 것을 의미합니다.

클래스를 클래스 생성기로 사용할 수 있습니다.좋아요 (일부 오프커프 코드에서는 :)

class gen(object):
    class base_1(object): pass
    ...
    class base_n(object): pass

    def __init__(self, ...):
        ...
    def mk_cls(self, ..., type):
        '''makes a class based on the type passed in, the current state of
           the class, and the other inputs to the method'''

이 기능이 필요할 때는 분명하게 알 수 있을 것입니다.이와 유사한 작업을 수행할 필요가 없다면 사용 사례가 좋지 않을 수도 있습니다.

메타 클래스를 취급하는 경우를 제외하고는 이 작업을 수행하는 데 아무런 이점이 없습니다.

클래스: 스위트룸은 정말 당신이 생각하는 것과 다릅니다.그것은 이상한 범위이고, 이상한 일을 합니다.그것은 정말 수업조차 되지 않습니다!클래스 이름, 기본값, 속성 사전 및 메타 클래스와 같은 일부 변수를 수집하는 방법일 뿐입니다.

이름, 사전 및 기본값은 모두 메타 클래스인 함수에 전달된 다음 class: suite가 있었던 범위의 변수 'name'에 할당됩니다.

메타 클래스를 혼란스럽게 하고 실제로 주식 표준 클래스 내에 클래스를 중첩함으로써 얻을 수 있는 것은 코드를 읽기 어렵고 코드를 이해하기 어렵고 '클래스' 범위가 다른 파이썬 범위와 완전히 다른 이유를 잘 알지 못하면 이해하기 어려운 이상한 오류입니다.

이 기능의 좋은 사용 사례는 오류/예외 처리입니다. 예:

class DownloadManager(object):
    class DowndloadException(Exception):
        pass

    def download(self):
        ...

이제 코드를 읽고 있는 사람은 이 클래스와 관련된 모든 가능한 예외를 알고 있습니다.

클래스 내부 또는 외부에서 정의된 어떤 방식으로든 작동합니다.다음은 도우미 클래스 EmpInit가 클래스 내에 포함된 직원 급여 일정 프로그램입니다. 직원:

class   Employee:

    def level(self, j):
        return j * 5E3

    def __init__(self, name, deg, yrs):
        self.name = name
        self.deg = deg
        self.yrs = yrs
        self.empInit = Employee.EmpInit(self.deg, self.level)
        self.base = Employee.EmpInit(self.deg, self.level).pay

    def pay(self):
        if self.deg in self.base:
            return self.base[self.deg]() + self.level(self.yrs)
        print(f"Degree {self.deg} is not in the database {self.base.keys()}")
        return 0

    class   EmpInit:

        def __init__(self, deg, level):
            self.level = level
            self.j = deg
            self.pay = {1: self.t1, 2: self.t2, 3: self.t3}

        def t1(self):   return self.level(1*self.j)
        def t2(self):   return self.level(2*self.j)
        def t3(self):   return self.level(3*self.j)

if  __name__ == '__main__':
    for loop in range(10):
        lst = [item for item in input(f"Enter name, degree and years : ").split(' ')]
        e1 = Employee(lst[0], int(lst[1]), int(lst[2]))
        print(f'Employee {e1.name} with degree {e1.deg} and years {e1.yrs} is making {e1.pay()} dollars')
        print("EmpInit deg {0}\nlevel {1}\npay[deg]: {2}".format(e1.empInit.j, e1.empInit.level, e1.base[e1.empInit.j]))

외부에서 정의하려면 EmpInit을 제거하고 EmpInit을 변경합니다.EmpInit()는 일반적인 "has-a" 구성으로 간단히 EmpInit()을 나타냅니다.그러나 Empire가 EmpInit의 컨트롤러이고 사용자가 EmpInit를 직접 인스턴스화하거나 인터페이스하지 않기 때문에 독립 실행형 클래스가 아니기 때문에 EmpInit를 내부에서 정의하는 것이 타당합니다.또한 인스턴스 메서드 수준()은 두 클래스 모두에서 호출되도록 설계되었습니다.따라서 Empinit에 전달할 필요 없이 Empinit에서 정적 메서드로 편리하게 정의할 수 있습니다.수평의

언급URL : https://stackoverflow.com/questions/78799/is-there-a-benefit-to-defining-a-class-inside-another-class-in-python

반응형