developer tip

Python에서 가상 메서드를 구현하는 방법은 무엇입니까?

copycodes 2020. 11. 6. 18:55
반응형

Python에서 가상 메서드를 구현하는 방법은 무엇입니까?


PHP 또는 Java의 가상 방법을 알고 있습니다.

파이썬에서 어떻게 구현할 수 있습니까?

아니면 추상 클래스에서 빈 메서드를 정의하고 재정의해야합니까?


물론, 기본 클래스에서 메서드를 정의 할 필요조차 없습니다. 파이썬에서 메서드는 가상보다 낫습니다 . 파이썬에서 타이핑하는 것이 오리 타이핑 이기 때문에 완전히 동적 입니다.

class Dog:
  def say(self):
    print "hau"

class Cat:
  def say(self):
    print "meow"

pet = Dog()
pet.say() # prints "hau"
another_pet = Cat()
another_pet.say() # prints "meow"

my_pets = [pet, another_pet]
for a_pet in my_pets:
  a_pet.say()

CatDog파이썬에서도이 동작을 할 수 있도록 공통 기본 클래스에서 파생 필요가 없습니다 - 당신은 무료로 얻을 수 있습니다. 즉 어떤 프로그래머가 더 잘 문서화하고 부과하는 더 엄격한 방법으로 자신의 클래스 계층을 정의하는 것을 선호했다 일부 입력의 엄격합니다. 이것은 또한 가능합니다-예를 들어 abc표준 모듈을보십시오 .


Python 메서드는 항상 가상입니다.


raise NotImplementedError()

메서드를 구현하지 않는 "추상"기본 클래스의 "순수 가상 메서드"에서 발생하는 권장 예외입니다.

https://docs.python.org/3.5/library/exceptions.html#NotImplementedError 말한다 :

이 예외는 RuntimeError. 사용자 정의 기본 클래스에서 추상 메서드는 메서드를 재정의하기 위해 파생 클래스가 필요할 때이 예외를 발생시켜야합니다.

다른 사람들이 말했듯이 이것은 대부분 문서 규칙이며 필수는 아니지만 이렇게하면 누락 된 속성 오류보다 더 의미있는 예외가 발생합니다.

예 :

class Base(object):
    def virtualMethod(self):
        raise NotImplementedError()
    def usesVirtualMethod(self):
        return self.virtualMethod() + 1

class Derived(Base):
    def virtualMethod(self):
        return 1

print Derived().usesVirtualMethod()
Base().usesVirtualMethod()

제공합니다 :

2
Traceback (most recent call last):
  File "./a.py", line 13, in <module>
    Base().usesVirtualMethod()
  File "./a.py", line 6, in usesVirtualMethod
    return self.virtualMethod() + 1
  File "./a.py", line 4, in virtualMethod
    raise NotImplementedError()
NotImplementedError

관련 : 파이썬에서 추상 클래스를 만드는 것이 가능합니까?


실제로 버전 2.6에서 파이썬은 추상 기본 클래스 라는 것을 제공하며 다음 과 같이 명시 적으로 가상 메서드를 설정할 수 있습니다.

from abc import ABCMeta
from abc import abstractmethod
...
class C:
    __metaclass__ = ABCMeta
    @abstractmethod
    def my_abstract_method(self, ...):

클래스가 이미 메타 클래스를 사용하는 클래스에서 상속하지 않는 경우 매우 잘 작동합니다.

출처 : http://docs.python.org/2/library/abc.html


Python 메서드는 항상 가상입니다.

Ignacio가 말한 것처럼 어쨌든 클래스 상속은 원하는 것을 구현하는 더 나은 접근 방식 일 수 있습니다.

class Animal:
    def __init__(self,name,legs):
        self.name = name
        self.legs = legs

    def getLegs(self):
        return "{0} has {1} legs".format(self.name, self.legs)

    def says(self):
        return "I am an unknown animal"

class Dog(Animal): # <Dog inherits from Animal here (all methods as well)

    def says(self): # <Called instead of Animal says method
        return "I am a dog named {0}".format(self.name)

    def somethingOnlyADogCanDo(self):
        return "be loyal"

formless = Animal("Animal", 0)
rover = Dog("Rover", 4) #<calls initialization method from animal

print(formless.says()) # <calls animal say method

print(rover.says()) #<calls Dog says method
print(rover.getLegs()) #<calls getLegs method from animal class

결과는 다음과 같아야합니다.

I am an unknown animal
I am a dog named Rover
Rover has 4 legs

C ++의 가상 메서드 (기본 클래스에 대한 참조 또는 포인터를 통해 파생 클래스의 메서드 구현 호출)와 같은 것은 Python에서 입력이 없기 때문에 Python에서는 의미가 없습니다. (하지만 가상 메서드가 Java와 PHP에서 어떻게 작동하는지 모르겠습니다.)

그러나 "가상"이란 상속 계층 구조에서 최하위 구현을 호출하는 것을 의미한다면 여러 답변이 지적했듯이 Python에서 항상 얻는 것입니다.

글쎄, 거의 항상 ...

As dplamp pointed out, not all methods in Python behave like that. Dunder method don't. And I think that's a not so well known feature.

Consider this artificial example

class A:
    def prop_a(self):
        return 1
    def prop_b(self):
        return 10 * self.prop_a()

class B(A):
    def prop_a(self):
        return 2

Now

>>> B().prop_b()
20
>>> A().prob_b()
10

However, consider this one

class A:
    def __prop_a(self):
        return 1
    def prop_b(self):
        return 10 * self.__prop_a()

class B(A):
    def __prop_a(self):
        return 2

Now

>>> B().prop_b()
10
>>> A().prob_b()
10

The only thing we've changes was making prop_a() a dunder method.

A problem with the first behavior can be that you can't change the behavior of prop_a() in the derived class without impacting the behavior of prop_b(). This very nice talk by Raymond Hettinger gives an example for a use case where this is inconvenient.

참고URL : https://stackoverflow.com/questions/4714136/how-to-implement-virtual-methods-in-python

반응형