Python Language
수업
수색…
소개
파이썬은 대중적인 스크립팅 언어로서뿐만 아니라 객체 지향 프로그래밍 패러다임을 지원합니다. 클래스는 데이터를 기술하고 그 데이터를 조작하는 메소드를 제공합니다.이 메소드는 모두 단일 객체 아래에 포함됩니다. 또한 클래스는 구체적인 구현 세부 사항을 추상적 인 데이터 표현과 분리하여 추상화를 허용합니다.
클래스를 사용하는 코드는 일반적으로 읽고, 이해하고 유지하는 것이 더 쉽습니다.
기본 상속
파이썬에서의 상속은 자바, C ++ 등의 다른 객체 지향 언어에서 사용되는 유사한 개념을 기반으로합니다. 새로운 클래스는 다음과 같이 기존 클래스에서 파생 될 수 있습니다.
class BaseClass(object):
pass
class DerivedClass(BaseClass):
pass
BaseClass
는 이미 존재하는 ( 부모 ) 클래스이고 DerivedClass
는 BaseClass
에서 속성을 상속 (또는 서브 클래스 )하는 새로운 ( 하위 ) 클래스입니다. 참고 : 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)
: DerivedClass
가 BaseClass
의 서브 클래스 인 경우 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
.
class A(object):
def f(self, x):
return 2 * x
A.f
# <function A.f at ...> (in Python 3.x)
파이썬 2에서의 동작은 다르다 : 클래스 내의 함수 객체는 명시 적으로 instancemethod
유형의 객체로 대체되었다.이 객체는 특정 클래스 인스턴스에 바인딩되지 않았기 때문에 언 바운드 메소드 라고 불렸다. .__func__
속성을 사용하여 기본 함수에 액세스 할 수 .__func__
.
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에서는 그 차이가 인정됩니다.
import inspect
inspect.isfunction(A.f)
# True
inspect.ismethod(A.f)
# False
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.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에서는 구식 클래스가 제거되었습니다.
파이썬 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 알고리즘은
- 깊이 우선 (예 :
FooBar
,Foo
) - 공유 된 부모 (
object
)가 자식 (Bar
)에 의해 차단되고 - 순환 관계는 허용되지 않습니다.
예를 들어 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
, classmethod
및 property
를 구현하는 데 사용됩니다. 점선으로 된 룩업 (예 : 속성 bar
찾는 Foo
클래스의 인스턴스 foo
, 즉 foo.bar
)는 다음 알고리즘을 사용합니다 :
bar
는Foo
에서 수업을 들여다Foo
. 이 존재하고 데이터 디스크립터이면 데이터 서술자가 사용된다. 이것이property
이 인스턴스의 데이터에 대한 액세스를 제어 할 수있는 방법이며 인스턴스는이를 무시할 수 없습니다. 데이터 디스크립터 가 없다면bar
는__dict__
인스턴스에서 조회됩니다. 따라서 점으로 둘러싼 인스턴스에서 호출되는 메서드를 재정의하거나 차단할 수 있습니다. 인스턴스에bar
가 있으면 사용됩니다. 그렇지 않다면 우리는Foo
클래스에서bar
찾습니다. 그것은 기술자 인 경우, 기술자 프로토콜이 사용됩니다. 이것은 함수 (이 경우, 언 바운드 메소드),classmethod
및staticmethod
가 구현되는 방법입니다. 그렇지 않으면 단순히 객체를 반환하거나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 + ".")
그러나이 코드에는 두 가지 주요 문제점이 있습니다.
매개 변수의
first_name
과last_name
당신이 전체 이름을 입력 할 수 있기 때문에, 지금은 오해의 소지가 있습니다first_name
. 또한 이러한 종류의 유연성을 가진 더 많은 경우 및 / 또는 더 많은 매개 변수가있는 경우 if / elif / else 분기가 성가신 속도로 진행될 수 있습니다.꽤 중요하지는 않지만 여전히 지적할만한 가치가 있습니다.
last_name
이None
이지만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
대신 cls
를 from_full_name
. 클래스 메소드는 전체 클래스에 적용되며 주어진 클래스의 인스턴스는 아닙니다 (이는 일반적으로 self
나타내는 것입니다). 따라서 cls
가 Person
클래스 Person
경우 from_full_name
클래스 메소드의 반환 값은 Person(first_name, last_name, age)
이며 Person
클래스의 인스턴스를 만들기 위해 Person
의 __init__
을 사용합니다. 우리가 서브 클래스 만들 것 인 경우에 특히, Employee
의 Person
, 다음 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.
기타 참고 문헌 :
https://docs.python.org/2/library/functions.html#classmethod
https://docs.python.org/3.5/library/functions.html#classmethod
수업 구성
클래스 구성은 객체 간의 명시 적 관계를 허용합니다. 이 예에서 사람들은 국가에 속한 도시에 산다. 구성을 통해 사람들은 자신의 나라에 살고있는 모든 사람들의 수에 접근 할 수 있습니다.
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))
위의 예를 볼 때주의해야 할 몇 가지 사항이 있습니다.
- 클래스는 속성 (데이터)과 메소드 (함수)로 구성됩니다.
- 속성 및 메소드는 단순히 일반 변수 및 함수로 정의됩니다.
- 해당 docstring에서 언급했듯이
__init__()
메서드를 초기화 프로그램 이라고합니다. 다른 객체 지향 언어의 생성자와 동일하며 새 객체 또는 클래스의 새 인스턴스를 만들 때 처음 실행되는 메서드입니다. - 전체 클래스에 적용되는 속성이 먼저 정의되며 클래스 속성 이라고 합니다 .
- 클래스의 특정 인스턴스 (오브젝트)에 적용되는 속성을 인스턴스 속성 이라고 합니다 . 그들은 일반적으로
__init__()
내부에 정의됩니다. 이것은 필요하지 않지만__init__()
외부에서 정의 된 속성은 정의되기 전에 액세스되는 위험을 감수하기 때문에 권장됩니다. - 클래스 정의에 포함 된 모든 메소드는 해당 객체를 첫 번째 매개 변수로 전달합니다.
self
라는 단어는이 매개 변수에 사용됩니다 (self
사용법은 관례에 따라 실제로self
라는 단어가 파이썬에서 고유 한 의미가 없기 때문에 이것은 파이썬에서 가장 존경받는 관례 중 하나이며 항상 따라야합니다). - 다른 언어로 객체 지향 프로그래밍에 익숙한 사람들은 몇 가지 사실에 놀라실 수 있습니다. 하나는 파이썬에는
private
요소에 대한 개념이 없기 때문에 기본적으로 모든 것이 C ++ / Javapublic
키워드의 동작을 모방하는 것입니다. 자세한 내용은이 페이지의 "비공개 클래스 멤버"예제를 참조하십시오. - 클래스의 메서드 중 일부는
__functionname__(self, other_stuff)
과 같은 형식을 갖습니다. 이러한 모든 메소드를 "마법 메소드"라고하며 파이썬에서 클래스의 중요한 부분입니다. 예를 들어, 파이썬에서 연산자 오버로딩은 마술 방식으로 구현됩니다. 자세한 내용 은 관련 설명서를 참조하십시오.
이제 Person
클래스의 몇 가지 인스턴스를 만들어 보자!
>>> # Instances
>>> kelly = Person("Kelly")
>>> joseph = Person("Joseph")
>>> john_doe = Person("John Doe")
현재 우리는 세 개의 Person
객체, kelly
, joseph
및 john_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