수색…


소개

파이썬은 대중적인 스크립팅 언어로서뿐만 아니라 객체 지향 프로그래밍 패러다임을 지원합니다. 클래스는 데이터를 기술하고 그 데이터를 조작하는 메소드를 제공합니다.이 메소드는 모두 단일 객체 아래에 포함됩니다. 또한 클래스는 구체적인 구현 세부 사항을 추상적 인 데이터 표현과 분리하여 추상화를 허용합니다.

클래스를 사용하는 코드는 일반적으로 읽고, 이해하고 유지하는 것이 더 쉽습니다.

기본 상속

파이썬에서의 상속은 자바, C ++ 등의 다른 객체 지향 언어에서 사용되는 유사한 개념을 기반으로합니다. 새로운 클래스는 다음과 같이 기존 클래스에서 파생 될 수 있습니다.

class BaseClass(object):
    pass

class DerivedClass(BaseClass):
    pass

BaseClass 는 이미 존재하는 ( 부모 ) 클래스이고 DerivedClassBaseClass 에서 속성을 상속 (또는 서브 클래스 )하는 새로운 ( 하위 ) 클래스입니다. 참고 : Python 2.2에서 모든 클래스는 모든 내장 유형의 기본 클래스 인 object 클래스를 암시 적으로 상속 합니다.

아래 예제에서 부모 Rectangle 클래스를 정의합니다.이 클래스는 object 를 암묵적으로 상속 object .

class Rectangle():
    def __init__(self, w, h):
        self.w = w
        self.h = h
    
    def area(self):
        return self.w * self.h
        
    def perimeter(self):
        return 2 * (self.w + self.h)

Rectangle 클래스는 Square 클래스를 정의하기위한 기본 클래스로 사용할 수 있습니다. 사각형은 사각형의 특별한 경우입니다.

class Square(Rectangle):
    def __init__(self, s):
        # call parent constructor, w and h are both s
        super(Square, self).__init__(s, s)
        self.s = s

Square 클래스는 자동으로 Rectangle 클래스와 객체 클래스의 모든 속성을 상속받습니다. super()Rectangle 클래스의 __init__() 메서드를 호출하는 데 사용되며 기본적으로 오버라이드 된 기본 클래스의 메서드를 호출합니다. 참고 : Python 3에서 super() 에는 인수가 필요하지 않습니다.

파생 클래스 객체는 기본 클래스의 속성에 액세스하고 수정할 수 있습니다.

r.area()
# Output: 12
r.perimeter()  
# Output: 14

s.area()
# Output: 4
s.perimeter()
# Output: 8

상속과 함께 작동하는 내장 함수

issubclass(DerivedClass, BaseClass) : DerivedClassBaseClass 의 서브 클래스 인 경우 True 반환합니다.

isinstance(s, Class) : 반환 True 의는의 인스턴스의 경우는 Class 또는 파생 클래스의 Class

# subclass check        
issubclass(Square, Rectangle)
# Output: True

# instantiate
r = Rectangle(3, 4)
s = Square(2)

isinstance(r, Rectangle)  
# Output: True
isinstance(r, Square)
# Output: False
# A rectangle is not a square

isinstance(s, Rectangle)
# Output: True
# A square is a rectangle
isinstance(s, Square)
# Output: True

클래스 및 인스턴스 변수

인스턴스 변수는 각 인스턴스마다 고유하며 클래스 변수는 모든 인스턴스에서 공유됩니다.

class C:
    x = 2  # class variable

    def __init__(self, y):
        self.y = y  # instance variable

C.x
# 2
C.y
# AttributeError: type object 'C' has no attribute 'y'

c1 = C(3)
c1.x
# 2
c1.y
# 3

c2 = C(4)
c2.x
# 2
c2.y
# 4

클래스 변수는이 클래스의 인스턴스에서 액세스 할 수 있지만 class 속성에 할당하면 클래스 변수를 음영 처리하는 인스턴스 변수가 만들어집니다

c2.x = 4
c2.x
# 4
C.x
# 2

인스턴스에서 클래스 변수를 변경 하면 예기치 않은 결과가 발생할 수 있습니다.

class D:
    x = []
    def __init__(self, item):
        self.x.append(item)  # note that this is not an assigment!

d1 = D(1)
d2 = D(2)

d1.x
# [1, 2]
d2.x
# [1, 2]
D.x
# [1, 2]

바운드, 언 바운드 및 정적 메서드

바운드 및 언 바운드 메소드에 대한 아이디어는 Python 3에서 제거되었습니다 . 파이썬 3에서는 클래스 내에서 메소드를 선언 할 때 def 키워드를 사용하므로 함수 객체를 만듭니다. 이것은 정규 함수이며, 그 주변 클래스는 네임 스페이스로 작동합니다. 다음 예제에서 우리는 클래스 A 내의 메소드 f 선언하고 함수 Af .

Python 3.x 3.0
class A(object):
    def f(self, x):
        return 2 * x
A.f
# <function A.f at ...>  (in Python 3.x)

파이썬 2에서의 동작은 다르다 : 클래스 내의 함수 객체는 명시 적으로 instancemethod 유형의 객체로 대체되었다.이 객체는 특정 클래스 인스턴스에 바인딩되지 않았기 때문에 언 바운드 메소드 라고 불렸다. .__func__ 속성을 사용하여 기본 함수에 액세스 할 수 .__func__ .

파이썬 2.x 2.3
A.f
# <unbound method A.f>   (in Python 2.x)
A.f.__class__
# <type 'instancemethod'>
A.f.__func__
# <function f at ...>

후자의 동작은 검사에 의해 확인됩니다. Python 3에서는 함수가 함수로 인식되지만 Python 2에서는 그 차이가 인정됩니다.

Python 3.x 3.0
import inspect

inspect.isfunction(A.f)
# True
inspect.ismethod(A.f)
# False
파이썬 2.x 2.3
import inspect

inspect.isfunction(A.f)
# False
inspect.ismethod(A.f)
# True

두 버전의 Python에서 함수 / 메소드 Af 는 클래스 A 의 인스턴스를 첫 번째 인수로 전달하면 직접 호출 할 수 있습니다.

A.f(1, 7)
# Python 2: TypeError: unbound method f() must be called with
#                      A instance as first argument (got int instance instead) 
# Python 3: 14   
a = A()
A.f(a, 20)
# Python 2 & 3: 40

이제 가정 a 클래스의 인스턴스 , 무엇 A af 다음? 음, 직관적으로이 같은 방법이어야한다 f 클래스의 만은 어떻게 든이 개체에 적용되었는지 "알고있다"해야 에 바인딩 파이썬이가 호출 방법 - A a a .

다음 본질적인 측면 사항이다 : 기록 af 마법 호출 __getattribute__ 방법 먼저 확인 여부, a a 속성 이름 갖는다 f (그렇지 않음), 다음 클래스 확인 A 이 같은 이름의 방법에 포함되어 있는지 여부를 (그것을한다) m method 있는 새로운 객체 m 을 생성한다.이 객체는 원래의 Af 에 대한 참조가 m.__func__ 에 있고, 객체 a 에 대한 참조가 m.__self__ . 이 객체를 함수로 호출하면 m(...) => m.__func__(m.__self__, ...) 됩니다. 따라서이 객체는 호출 될 때 바인딩 된 객체를 첫 번째 인수로 제공하는 것을 알고 있기 때문에 바운드 메소드 라고합니다. (이러한 것들은 Python 2와 3에서 같은 방식으로 작동합니다).

a = A()
a.f
# <bound method A.f of <__main__.A object at ...>>
a.f(2)
# 4

# Note: the bound method object a.f is recreated *every time* you call it:
a.f is a.f  # False
# As a performance optimization you can store the bound method in the object's
# __dict__, in which case the method object will remain fixed:
a.f = a.f
a.f is a.f  # True

마지막으로, 파이썬에는 클래스 메소드정적 메소드 가 있습니다. 특별한 종류의 메소드입니다. 클래스 메서드는 일반 메서드와 동일한 방식으로 작동하지만 개체 대신 호출되는 경우 개체 대신 개체 클래스 에 바인딩됩니다. 따라서 m.__self__ = type(a) . 이러한 바운드 메소드를 호출하면 첫 번째 인수로 a 클래스를 전달합니다. 정적 메서드는 훨씬 단순합니다. 아무 것도 바인딩하지 않고 변형없이 기본 함수를 반환하기 만합니다.

class D(object):
    multiplier = 2

    @classmethod
    def f(cls, x):
        return cls.multiplier * x

    @staticmethod
    def g(name):
        print("Hello, %s" % name)

D.f
# <bound method type.f of <class '__main__.D'>>
D.f(12)
# 24
D.g
# <function D.g at ...>
D.g("world")
# Hello, world

클래스 메소드는 인스턴스에서 액세스 할 때에도 클래스에 바인딩됩니다.

d = D()
d.multiplier = 1337
(D.multiplier, d.multiplier)
# (2, 1337)
d.f
# <bound method D.f of <class '__main__.D'>>
d.f(10)
# 20

가장 낮은 레벨에서 함수, 메소드, 정적 메소드 등이 실제로 __get__ , __set __ 및 선택적으로 __del__ 특수 메소드를 호출하는 기술자 임을 __get__ 필요가 있습니다. classmethod 및 staticmethod에 대한 자세한 내용은 다음을 참조하십시오.

새로운 스타일 대 구식 클래스

Python 2.x 2.2.0

Python 2.2에는 새로운 스타일의 클래스가 도입되어 클래스유형 을 통합했습니다. 최상위 레벨 object 유형을 상속합니다. 새 스타일 클래스는 사용자 정의 유형 이며 내장 유형과 매우 유사합니다.

# new-style class
class New(object):
    pass

# new-style instance
new = New()

new.__class__
# <class '__main__.New'>
type(new)
# <class '__main__.New'>
issubclass(New, object)
# True

구식 클래스는 object 에서 상속받지 않습니다 . 구식 인스턴스는 항상 기본 제공 instance 유형으로 구현됩니다.

# old-style class
class Old:
    pass

# old-style instance
old = Old()

old.__class__
# <class __main__.Old at ...>
type(old)
# <type 'instance'>
issubclass(Old, object)
# False
Python 3.x 3.0.0

Python 3에서는 구식 클래스가 제거되었습니다.

파이썬 3의 새로운 스타일의 클래스는 object 에서 암묵적으로 상속되므로 더 이상 MyClass(object) 를 지정할 필요가 없습니다.

class MyClass:
    pass

my_inst = MyClass()

type(my_inst)
# <class '__main__.MyClass'>
my_inst.__class__
# <class '__main__.MyClass'>
issubclass(MyClass, object)
# True

인스턴스 변수의 기본값

변수에 변경 불가능한 유형 (예 : 문자열)의 값이 들어 있으면 다음과 같이 기본값을 할당하는 것이 좋습니다.

class Rectangle(object):
    def __init__(self, width, height, color='blue'):
        self.width = width
        self.height = height
        self.color = color
    
    def area(self):
        return self.width  * self.height 

# Create some instances of the class
default_rectangle = Rectangle(2, 3)
print(default_rectangle.color) # blue

red_rectangle = Rectangle(2, 3, 'red')
print(red_rectangle.color) # red

생성자의 목록과 같은 변경 가능한 객체를 초기화 할 때는주의해야합니다. 다음 예제를 고려하십시오.

class Rectangle2D(object):
    def __init__(self, width, height, pos=[0,0], color='blue'):  
        self.width = width
        self.height = height
        self.pos = pos
        self.color = color

r1 = Rectangle2D(5,3)
r2 = Rectangle2D(7,8)
r1.pos[0] = 4
r1.pos # [4, 0]
r2.pos # [4, 0] r2's pos has changed as well

이 동작은 파이썬 기본 매개 변수가 함수 선언시가 아니라 함수 실행시 바인딩된다는 사실 때문에 발생합니다. 인스턴스간에 공유되지 않는 기본 인스턴스 변수를 가져 오려면 다음과 같은 구문을 사용해야합니다.

class Rectangle2D(object):
    def __init__(self, width, height, pos=None, color='blue'):  
        self.width = width
        self.height = height
        self.pos = pos or [0, 0] # default value is [0, 0]
        self.color = color

r1 = Rectangle2D(5,3)
r2 = Rectangle2D(7,8)
r1.pos[0] = 4
r1.pos # [4, 0]
r2.pos # [0, 0] r2's pos hasn't changed 

Mutable Default Arguments"Least Astonishment"및 Mutable Default Argument를 참고하십시오 .

다중 상속

파이썬은 C3 선형화 알고리즘을 사용하여 메소드를 포함한 클래스 속성을 해석하는 순서를 결정합니다. 이를 MRO (Method Resolution Order)라고합니다.

다음은 간단한 예입니다.

class Foo(object):
    foo = 'attr foo of Foo'
    

class Bar(object):
    foo = 'attr foo of Bar' # we won't see this.
    bar = 'attr bar of Bar'

class FooBar(Foo, Bar):
    foobar = 'attr foobar of FooBar'

이제 FooBar를 인스턴스화하면 foo 속성을 검색하면 Foo의 속성이 먼저 발견됩니다.

fb = FooBar()

>>> fb.foo
'attr foo of Foo'

FooBar의 MRO는 다음과 같습니다.

>>> FooBar.mro()
[<class '__main__.FooBar'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <type 'object'>]

파이썬의 MRO 알고리즘은

  1. 깊이 우선 (예 : FooBar , Foo )
  2. 공유 된 부모 ( object )가 자식 ( Bar )에 의해 차단되고
  3. 순환 관계는 허용되지 않습니다.

예를 들어 Bar는 FooBar에서 상속받을 수 없지만 FooBar는 Bar에서 상속합니다.

Python의 포괄적 인 예제는 wikipedia 항목을 참조하십시오.

상속의 또 다른 강력한 기능은 super 입니다. super는 부모 클래스 기능을 가져올 수 있습니다.

class Foo(object):
    def foo_method(self):
        print "foo Method"

class Bar(object):
    def bar_method(self):
        print "bar Method"

class FooBar(Foo, Bar):
    def foo_method(self):
        super(FooBar, self).foo_method()

클래스의 init 메소드로 다중 상속, 모든 클래스가 자신의 init 메소드를 가질 때 다중 불허가를 시도한 다음 init 메소드가 먼저 상속받은 클래스를 호출합니다.

아래 예제 만위한 Foo 클래스 init 메소드 호출하기 Bar 클래스 init 호출 안 함

    class Foo(object):
        def __init__(self):
            print "foo init"

    class Bar(object):
        def __init__(self):
            print "bar init"

    class FooBar(Foo, Bar):
        def __init__(self):
            print "foobar init"
            super(FooBar, self).__init__()

    a = FooBar()

산출:

    foobar init
    foo init

하지만 Bar 클래스가 상속되지 않는다는 의미는 아닙니다. 최종 FooBar 클래스의 인스턴스는 Bar 클래스와 Foo 클래스의 인스턴스이기도합니다.

print isinstance(a,FooBar)
print isinstance(a,Foo)
print isinstance(a,Bar) 

산출:

True
True
True

설명자 및 점으로 구분 된 조회

기술 __get__ 클래스의 (일반적으로) 속성이며 __get__ , __set__ 또는 __delete__ 특수 메소드가있는 객체입니다.

데이터 기술자__set__ 또는 __delete__ 중 하나 __set__ __delete__

이것들은 인스턴스에서 점으로 구분 된 조회를 제어 할 수 있으며 함수, staticmethod , classmethodproperty 를 구현하는 데 사용됩니다. 점선으로 된 룩업 (예 : 속성 bar 찾는 Foo 클래스의 인스턴스 foo , 즉 foo.bar )는 다음 알고리즘을 사용합니다 :

  1. barFoo 에서 수업을 들여다 Foo . 이 존재하고 데이터 디스크립터이면 데이터 서술자가 사용된다. 이것이 property 이 인스턴스의 데이터에 대한 액세스를 제어 할 수있는 방법이며 인스턴스는이를 무시할 수 없습니다. 데이터 디스크립터 가 없다면

  2. bar__dict__ 인스턴스에서 조회됩니다. 따라서 점으로 둘러싼 인스턴스에서 호출되는 메서드를 재정의하거나 차단할 수 있습니다. 인스턴스에 bar 가 있으면 사용됩니다. 그렇지 않다면 우리는

  3. Foo 클래스에서 bar 찾습니다. 그것은 기술자 인 경우, 기술자 프로토콜이 사용됩니다. 이것은 함수 (이 경우, 언 바운드 메소드), classmethodstaticmethod 가 구현되는 방법입니다. 그렇지 않으면 단순히 객체를 반환하거나 AttributeError

클래스 메소드 : 대체 이니셜 라이저

클래스 메소드는 클래스의 인스턴스를 빌드하는 다른 방법을 제시합니다. 설명하기 위해 예제를 살펴 보겠습니다.

상대적으로 간단한 Person 클래스가 있다고 가정 해 보겠습니다.

class Person(object):

    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age
        self.full_name = first_name + " " + last_name
    
    def greet(self):
        print("Hello, my name is " + self.full_name + ".")

성과 이름 대신 성명을 별도로 지정하여이 클래스의 인스턴스를 작성하는 방법이 있으면 편리 할 수 ​​있습니다. 이를 수행하는 한 가지 방법은 last_name 에 선택적 매개 변수를 지정하는 것입니다. 매개 변수가 주어지지 않으면 full_name을 전달합니다.

class Person(object):

    def __init__(self, first_name, age, last_name=None):
        if last_name is None:
            self.first_name, self.last_name = first_name.split(" ", 2)
        else:
            self.first_name = first_name
            self.last_name = last_name
        
        self.full_name = self.first_name + " " + self.last_name
        self.age = age

    def greet(self):
        print("Hello, my name is " + self.full_name + ".")

그러나이 코드에는 두 가지 주요 문제점이 있습니다.

  1. 매개 변수의 first_namelast_name 당신이 전체 이름을 입력 할 수 있기 때문에, 지금은 오해의 소지가 있습니다 first_name . 또한 이러한 종류의 유연성을 가진 더 많은 경우 및 / 또는 더 많은 매개 변수가있는 경우 if / elif / else 분기가 성가신 속도로 진행될 수 있습니다.

  2. 꽤 중요하지는 않지만 여전히 지적할만한 가치가 있습니다. last_nameNone 이지만 first_name 이 공백을 통해 두 개 이상의 것들로 분리되지 않으면 어떨까요? 입력 검증 및 / 또는 예외 처리의 또 다른 계층이 있습니다.

클래스 메소드를 입력하십시오. 단일 이니셜 라이저를 갖는 대신, from_full_name 이라는 개별 이니셜 라이저를 작성하고 (내장 된) classmethod 데코레이터로 데코 레이팅합니다.

class Person(object):

    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age
        self.full_name = first_name + " " + last_name
    
    @classmethod
    def from_full_name(cls, name, age):
        if " " not in name:
            raise ValueError
        first_name, last_name = name.split(" ", 2)
        return cls(first_name, last_name, age)
    
    def greet(self):
        print("Hello, my name is " + self.full_name + ".")

from_full_name 의 첫 번째 인수로 self 대신 clsfrom_full_name . 클래스 메소드는 전체 클래스에 적용되며 주어진 클래스의 인스턴스는 아닙니다 (이는 일반적으로 self 나타내는 것입니다). 따라서 clsPerson 클래스 Person 경우 from_full_name 클래스 메소드의 반환 값은 Person(first_name, last_name, age) 이며 Person 클래스의 인스턴스를 만들기 위해 Person__init__ 을 사용합니다. 우리가 서브 클래스 만들 것 인 경우에 특히, EmployeePerson , 다음 from_full_name 작업 중 것이다 Employee 뿐만 아니라 클래스입니다.

이것이 예상대로 작동한다는 것을 보여주기 위해, __init__ 에서 분기하지 않고 하나 이상의 방법으로 Person 의 인스턴스를 생성합시다.

In [2]: bob = Person("Bob", "Bobberson", 42)

In [3]: alice = Person.from_full_name("Alice Henderson", 31)

In [4]: bob.greet()
Hello, my name is Bob Bobberson.

In [5]: alice.greet()
Hello, my name is Alice Henderson.

기타 참고 문헌 :

수업 구성

클래스 구성은 객체 간의 명시 적 관계를 허용합니다. 이 예에서 사람들은 국가에 속한 도시에 산다. 구성을 통해 사람들은 자신의 나라에 살고있는 모든 사람들의 수에 접근 할 수 있습니다.

class Country(object):
    def __init__(self):
        self.cities=[]
        
    def addCity(self,city):
        self.cities.append(city)
        

class City(object):
    def __init__(self, numPeople):
        self.people = []
        self.numPeople = numPeople
        
        
    def addPerson(self, person):
        self.people.append(person)
    
    def join_country(self,country):
        self.country = country
        country.addCity(self)
        
        for i in range(self.numPeople):
                person(i).join_city(self)
  

class Person(object):
    def __init__(self, ID):
        self.ID=ID

    def join_city(self, city):
        self.city = city
        city.addPerson(self)
        
    def people_in_my_country(self):
        x= sum([len(c.people) for c in self.city.country.cities])
        return x
        
US=Country()
NYC=City(10).join_country(US)
SF=City(5).join_country(US)

print(US.cities[0].people[0].people_in_my_country())

# 15

원숭이 패치

이 경우 "원숭이 패치"는 정의 된 클래스에 새 변수 또는 메소드를 추가하는 것을 의미합니다. 예를 들어 클래스 A

class A(object):
    def __init__(self, num):
        self.num = num

    def __add__(self, other):
        return A(self.num + other.num)

그러나 이제는 코드에서 나중에 다른 함수를 추가하려고합니다. 이 함수가 다음과 같다고 가정하십시오.

def get_num(self):
    return self.num

그러나 이것을 어떻게 A 의 메소드로 추가할까요? 간단히 말해서 우리는 그 함수를 대입 문으로 A 배치해야합니다.

A.get_num = get_num

왜이게 효과가 있니? 함수는 다른 객체와 마찬가지로 객체이기 때문에 메서드는 클래스에 속하는 함수입니다.

함수 get_num 기존의 (이미 생성 된) 모든 A 와 새로운 A 인스턴스에서 사용할 수 있어야한다 A

이러한 추가 기능은 해당 클래스 (또는 그 서브 클래스)의 모든 인스턴스에서 자동으로 사용할 수 있습니다. 예 :

foo = A(42)

A.get_num = get_num

bar = A(6);

foo.get_num() # 42

bar.get_num() # 6

다른 언어와 달리이 기술은 특정 내장 유형에서는 작동하지 않으며 좋은 스타일로 간주되지 않습니다.

모든 클래스 멤버 나열

dir() 함수는 클래스의 멤버 목록을 얻는 데 사용할 수 있습니다.

dir(Class)

예 :

>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

"비 매직 (non-magic)"회원만을 보는 것이 일반적입니다. __ 시작하지 않는 이름을 가진 구성원을 나열하는 간단한 이해를 사용하여 수행 할 수 있습니다.

>>> [m for m in dir(list) if not m.startswith('__')]
['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

주의 사항 :

클래스는 __dir__() 메서드를 정의 할 수 있습니다. 이 메소드가 존재하면 dir()__dir__() 호출 할 것이고, 그렇지 않으면 파이썬은 그 클래스의 멤버리스트를 만들려고 시도 할 것이다. 이것은 dir 함수가 예기치 않은 결과를 가질 수 있음을 의미합니다. 공식적인 python 문서 에서 중요한 두 개의 인용문 :

객체가 dir ()을 제공하지 않으면 함수는 객체의 dict 속성 (정의 된 경우)과 객체 유형에서 정보를 수집하기 위해 최선을 다합니다. 결과 목록은 반드시 완전하지는 않으며 객체가 사용자 정의 getattr ()을 가질 때 부정확 할 수 있습니다.

참고 : dir ()은 주로 대화 형 프롬프트에서 사용하기 편리하기 때문에 엄격하게 또는 일관되게 정의 된 이름 집합을 제공하려고 시도하는 것보다 흥미로운 이름 집합을 제공하려고 시도하며 자세한 동작은 출시. 예를 들어, 인수가 클래스 인 경우 메타 클래스 속성은 결과 목록에 없습니다.

수업 소개

클래스는 특정 객체의 기본 특성을 정의하는 템플릿 역할을합니다. 다음은 그 예입니다.

class Person(object):
     """A simple class."""                            # docstring
     species = "Homo Sapiens"                         # class attribute

     def __init__(self, name):                        # special method
         """This is the initializer. It's a special
         method (see below).
         """
         self.name = name                             # instance attribute

     def __str__(self):                               # special method
         """This method is run when Python tries 
         to cast the object to a string. Return 
         this string when using print(), etc.
         """
         return self.name

     def rename(self, renamed):                       # regular method
         """Reassign and print the name attribute."""
         self.name = renamed
         print("Now my name is {}".format(self.name))

위의 예를 볼 때주의해야 할 몇 가지 사항이 있습니다.

  1. 클래스는 속성 (데이터)과 메소드 (함수)로 구성됩니다.
  2. 속성 및 메소드는 단순히 일반 변수 및 함수로 정의됩니다.
  3. 해당 docstring에서 언급했듯이 __init__() 메서드를 초기화 프로그램 이라고합니다. 다른 객체 지향 언어의 생성자와 동일하며 새 객체 또는 클래스의 새 인스턴스를 만들 때 처음 실행되는 메서드입니다.
  4. 전체 클래스에 적용되는 속성이 먼저 정의되며 클래스 속성 이라고 합니다 .
  5. 클래스의 특정 인스턴스 (오브젝트)에 적용되는 속성을 인스턴스 속성 이라고 합니다 . 그들은 일반적으로 __init__() 내부에 정의됩니다. 이것은 필요하지 않지만 __init__() 외부에서 정의 된 속성은 정의되기 전에 액세스되는 위험을 감수하기 때문에 권장됩니다.
  6. 클래스 정의에 포함 된 모든 메소드는 해당 객체를 첫 번째 매개 변수로 전달합니다. self 라는 단어는이 매개 변수에 사용됩니다 ( self 사용법은 관례에 따라 실제로 self 라는 단어가 파이썬에서 고유 한 의미가 없기 때문에 이것은 파이썬에서 가장 존경받는 관례 중 하나이며 항상 따라야합니다).
  7. 다른 언어로 객체 지향 프로그래밍에 익숙한 사람들은 몇 가지 사실에 놀라실 수 있습니다. 하나는 파이썬에는 private 요소에 대한 개념이 없기 때문에 기본적으로 모든 것이 C ++ / Java public 키워드의 동작을 모방하는 것입니다. 자세한 내용은이 페이지의 "비공개 클래스 멤버"예제를 참조하십시오.
  8. 클래스의 메서드 중 일부는 __functionname__(self, other_stuff) 과 같은 형식을 갖습니다. 이러한 모든 메소드를 "마법 메소드"라고하며 파이썬에서 클래스의 중요한 부분입니다. 예를 들어, 파이썬에서 연산자 오버로딩은 마술 방식으로 구현됩니다. 자세한 내용 은 관련 설명서를 참조하십시오.

이제 Person 클래스의 몇 가지 인스턴스를 만들어 보자!

>>> # Instances
>>> kelly = Person("Kelly")
>>> joseph = Person("Joseph")
>>> john_doe = Person("John Doe")

현재 우리는 세 개의 Person 객체, kelly , josephjohn_doe 있습니다.

점 연산자를 사용하여 각 인스턴스에서 클래스의 속성에 액세스 할 수 있습니다 . 다시 클래스와 인스턴스 속성의 차이점에 유의하십시오.

>>> # Attributes
>>> kelly.species
'Homo Sapiens'
>>> john_doe.species
'Homo Sapiens'
>>> joseph.species
'Homo Sapiens'
>>> kelly.name
'Kelly'
>>> joseph.name
'Joseph'

같은 도트 연산자를 사용하여 클래스의 메서드를 실행할 수 있습니다 . :

>>> # Methods
>>> john_doe.__str__()
'John Doe'
>>>  print(john_doe)
'John Doe'
>>>  john_doe.rename("John")
'Now my name is John'

속성

Python 클래스는 일반 객체 변수처럼 보이지만 사용자 정의 비헤이비어 및 문서를 첨부 할 수있는 속성을 지원 합니다 .

class MyClass(object):

    def __init__(self):
       self._my_string = ""
    
    @property
    def string(self):
        """A profoundly important string."""
        return self._my_string

    @string.setter
    def string(self, new_value):
        assert isinstance(new_value, str), \
               "Give me a string, not a %r!" % type(new_value)
        self._my_string = new_value

    @string.deleter
    def x(self):
        self._my_string = None

MyClass 클래스의 객체에는 .string 속성이있는 것처럼 .string . 그러나 이제는 동작이 엄격하게 제어됩니다.

mc = MyClass()
mc.string = "String!"
print(mc.string)
del mc.string

위와 같은 유용한 구문뿐만 아니라 등록 정보 구문을 사용하여 유효성 검증을 수행하거나 해당 속성에 다른 기능 보강을 추가 할 수 있습니다. 이는 공개 API에서 특히 유용 할 수 있습니다. 공개 API는 사용자에게 수준 높은 도움을 제공해야합니다.

속성의 또 다른 일반적인 사용은 클래스가 실제로 저장되지 않지만 요청 될 때만 계산되는 '가상 속성'즉 속성을 제공 할 수있게하는 것입니다.

class Character(object):
    def __init__(name, max_hp):
        self._name = name
        self._hp = max_hp
        self._max_hp = max_hp

    # Make hp read only by not providing a set method
    @property
    def hp(self):
        return self._hp

    # Make name read only by not providing a set method
    @property
    def name(self):
        return self.name

    def take_damage(self, damage):
        self.hp -= damage
        self.hp = 0 if self.hp <0 else self.hp

    @property
    def is_alive(self):
        return self.hp != 0

    @property
    def is_wounded(self):
        return self.hp < self.max_hp if self.hp > 0 else False

    @property
    def is_dead(self):
        return not self.is_alive

bilbo = Character('Bilbo Baggins', 100)
bilbo.hp
# out : 100
bilbo.hp = 200        
# out : AttributeError: can't set attribute
# hp attribute is read only.

bilbo.is_alive
# out : True
bilbo.is_wounded
# out : False
bilbo.is_dead
# out : False

bilbo.take_damage( 50 )

bilbo.hp
# out : 50

bilbo.is_alive
# out : True
bilbo.is_wounded
# out : True
bilbo.is_dead
# out : False

bilbo.take_damage( 50 )
bilbo.hp
# out : 0

bilbo.is_alive
# out : False
bilbo.is_wounded
# out : False
bilbo.is_dead
# out : True

싱글 톤 클래스

싱글 톤은 클래스의 인스턴스화를 하나의 인스턴스 / 객체로 제한하는 패턴입니다. python 단독 디자인 패턴에 대한 자세한 내용은 여기를 참조 하십시오 .

class Singleton:
    def __new__(cls):
        try:
            it = cls.__it__
        except AttributeError:
            it = cls.__it__ = object.__new__(cls)
        return it

    def __repr__(self):
        return '<{}>'.format(self.__class__.__name__.upper())

    def __eq__(self, other):
         return other is self

또 다른 방법은 클래스를 꾸미는 것입니다. 이 대답 의 예제를 따라 Singleton 클래스를 만듭니다.

class Singleton:
    """
    A non-thread-safe helper class to ease implementing singletons.
    This should be used as a decorator -- not a metaclass -- to the
    class that should be a singleton.

    The decorated class can define one `__init__` function that
    takes only the `self` argument. Other than that, there are
    no restrictions that apply to the decorated class.

    To get the singleton instance, use the `Instance` method. Trying
    to use `__call__` will result in a `TypeError` being raised.

    Limitations: The decorated class cannot be inherited from.

    """

    def __init__(self, decorated):
        self._decorated = decorated

    def Instance(self):
        """
        Returns the singleton instance. Upon its first call, it creates a
        new instance of the decorated class and calls its `__init__` method.
        On all subsequent calls, the already created instance is returned.

        """
        try:
            return self._instance
        except AttributeError:
            self._instance = self._decorated()
            return self._instance

    def __call__(self):
        raise TypeError('Singletons must be accessed through `Instance()`.')

    def __instancecheck__(self, inst):
        return isinstance(inst, self._decorated)

사용하려면 Instance 메서드를 사용할 수 있습니다.

@Singleton
class Single:
    def __init__(self):
        self.name=None
        self.val=0
    def getName(self):
        print(self.name)

x=Single.Instance()
y=Single.Instance()
x.name='I\'m single'
x.getName() # outputs I'm single
y.getName() # outputs I'm single


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow