Python 진급 학습은 Python 클래스의 원조-원류를 탐색합니다.
type()
를 사용하여 Python의 객체 유형 보기
In [11]: #
In [12]: type(10)
Out[12]: int
In [13]: type(3.1415926)
Out[13]: float
In [14]: #
In [15]: type('a')
Out[15]: str
In [16]: type("abc")
Out[16]: str
In [17]: #
In [18]: type(list)
Out[18]: type
In [19]: type([])
Out[19]: list
In [20]: #
In [21]: type(set)
Out[21]: type
In [22]: my_set = {1, 2, 3}
In [23]: type(my_set)
Out[23]: set
In [24]: #
In [25]: type(dict)
Out[25]: type
In [26]: my_dict = {'name': 'hui'}
In [27]: type(my_dict)
Out[27]: dict
In [28]: #
In [29]: def func():
...: pass
...:
In [30]: type(func)
Out[30]: function
In [31]: #
In [32]: class Foo(object):
...: pass
...:
In [33]: type(Foo)
Out[33]: type
In [34]: f = Foo()
In [35]: type(f)
Out[35]: __main__.Foo
In [36]: # type
In [37]: type(type)
Out[37]: type
알 수 있다숫자
1
는 int 형식의 대상입니다.문자열
abc
은str 형식의 대상입니다목록, 집합, 사전은 type 형식의 대상이며, 생성된 대상은 각각
list、set、dict
형식에 속한다함수
func
는function 형식의 대상입니다사용자 정의 클래스
Foo
가 만든 대상f
은 Foo
유형이고 그 클래스 자체Foo
는 type 형식의 대상이다.type
그 자체도 type 유형의 대상이다클래스도 대상
클래스는 같은 기능과 같은 속성을 가진 대상의 집합이다
대부분의 프로그래밍 언어에서, 클래스는 대상을 어떻게 생성하는지 설명하는 코드 세그먼트입니다.Python에서는 다음과 같은 이점이 있습니다.
In [1]: class ObjectCreator(object):
...: pass
...:
In [2]: my_object = ObjectCreator()
In [3]: print(my_object)
<__main__.ObjectCreator object at 0x0000021257B5A248>
하지만 파이썬의 클래스는 이뿐만이 아니다.클래스 역시 하나의 대상이다.네, 맞아요. 바로 상대예요.키워드class
를 사용하면 Python 해석기가 실행될 때 대상을 만들 수 있습니다.다음 코드 세그먼트:
>>> class ObjectCreator(object):
… pass
…
메모리에 대상을 만들 것입니다. 이름은 ObjectCreator
입니다.이 객체(클래스 객체 ObjectCreator)는 객체(인스턴스 객체)를 작성할 수 있습니다.그러나 그 본질은 여전히 하나의 대상이기 때문에 당신은 그것에 대해 다음과 같은 조작을 할 수 있다.1. 변수에 값을 부여할 수 있다
2. 복사할 수 있다
3. 당신은 그것을 위해 속성을 증가시킬 수 있습니다
4. 함수 매개 변수로 전달할 수 있다
다음 예제:
In [39]: class ObjectCreator(object):
...: pass
...:
In [40]: print(ObjectCreator)
<class '__main__.ObjectCreator'>
In [41]:#
In [41]: def out(obj):
...: print(obj)
...:
In [42]: out(ObjectCreator)
<class '__main__.ObjectCreator'>
In [43]: # hasattr
In [44]: hasattr(ObjectCreator, 'name')
Out[44]: False
In [45]: #
In [46]: ObjectCreator.name = 'hui'
In [47]: hasattr(ObjectCreator, 'name')
Out[47]: True
In [48]: ObjectCreator.name
Out[48]: 'hui'
In [49]: #
In [50]: obj = ObjectCreator
In [51]: obj()
Out[51]: <__main__.ObjectCreator at 0x212596a7248>
In [52]:
2. 동적으로 클래스 만들기
클래스도 대상이기 때문에, 실행할 때 다른 모든 대상처럼 동적으로 만들 수 있습니다.우선, 함수에 클래스를 만들 수 있습니다.
class
키워드를 사용하면 됩니다.
def cls_factory(cls_name):
"""
:param: cls_name
"""
if cls_name == 'Foo':
class Foo():
pass
return Foo # ,
elif cls_name == 'Bar':
class Bar():
pass
return Bar
IPython 퀴즈
MyClass = cls_factory('Foo')
In [60]: MyClass
Out[60]: __main__.cls_factory.<locals>.Foo # ,
In [61]: MyClass()
Out[61]: <__main__.cls_factory.<locals>.Foo at 0x21258b1a9c8>
그러나 이것은 아직 동적이지 않다. 왜냐하면 너는 여전히 전체 종류의 코드를 스스로 작성해야 하기 때문이다.클래스도 대상이기 때문에 어떤 것을 통해 생성되어야 한다.class 키워드를 사용하면 Python 해석기가 자동으로 이 대상을 만듭니다.그러나 Python의 대부분의 일과 마찬가지로, Python은 여전히 당신에게 수동으로 처리하는 방법을 제공합니다.
3. type으로 클래스 만들기
type에는 동적 생성 클래스가 완전히 다른 기능이 있습니다.
type는 클래스의 설명을 매개 변수로 받아들여서 클래스를 되돌려줍니다.(전입 파라미터에 따라 같은 함수가 두 가지 완전히 다른 용법을 가지고 있다는 것은 어리석은 일이지만, 이것은 Python에서 뒤로 호환성을 유지하기 위한 것이다)
type은 다음과 같이 작동합니다.
type (클래스 이름, 상위 클래스 이름으로 구성된 원조 (계승된 경우 비어 있을 수 있음), 속성을 포함하는 사전 (이름과 값)
예를 들어 다음 코드:
In [63]: class Test:
...: pass
...:
In [64]: Test()
Out[64]: <__main__.Test at 0x21258b34048>
In [65]:
수동으로 다음과 같이 만들 수 있습니다.
In [69]:# type
In [69]: Test2 = type('Test2', (), {})
In [70]: Test2()
Out[70]: <__main__.Test2 at 0x21259665808>
우리는 Test2
를 클래스 이름으로 사용하고 그것을 변수로 삼아 클래스의 인용으로 삼을 수도 있다.종류와 변수는 다르다. 여기는 일을 복잡하게 할 아무런 이유가 없다.즉, type 함수 중 첫 번째 실삼은 다른 이름이라고 할 수도 있고, 이 이름은 클래스의 이름을 나타낸다
In [71]: UserCls = type('User', (), {})
In [72]: print(UserCls)
<class '__main__.User'>
In [73]:
이 두 종류를 테스트하기 위해 help
사용
In [74]: # help Test
In [75]: help(Test)
Help on class Test in module __main__:
class Test(builtins.object)
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
In [76]: # help Test2
In [77]: help(Test2)
Help on class Test2 in module __main__:
class Test2(builtins.object)
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
In [78]:
4. type을 사용하여 속성이 있는 클래스 만들기
type는 클래스에 대한 속성을 정의하는 사전을 받아들입니다. 따라서
Parent = type('Parent', (), {'name': 'hui'})
번역:
class Parent(object):
name = 'hui'
또한 Parent
를 일반 클래스처럼 사용할 수 있습니다.
In [79]: Parent = type('Parent', (), {'name': 'hui'})
In [80]: print(Parent)
<class '__main__.Parent'>
In [81]: Parent.name
Out[81]: 'hui'
In [82]: p = Parent()
In [83]: p.name
Out[83]: 'hui'
물론 당신은 이 종류를 계승할 수 있습니다. 코드는 다음과 같습니다.
class Child1(Parent):
name = 'jack'
sex = ' '
class Child2(Parent):
name = 'mary'
sex = ' '
다음과 같이 쓸 수 있습니다.
Child1 = type('Child1', (Parent, ), {'name': 'jack', 'sex': ' '})
In [85]: Child2 = type('Child2', (Parent, ), {'name': 'mary', 'sex': ' '})
In [87]: Child1.name, Child1.sex
Out[87]: ('jack', ' ')
In [88]: Child2.name, Child2.sex
Out[88]: ('mary', ' ')
참고:5. type을 사용하여 방법이 있는 클래스를 만듭니다
결국 당신은 당신의 종류를 증가시키는 방법을 원할 것입니다.적절한 서명이 있는 함수를 정의하고 속성으로 값을 부여하면 됩니다.
인스턴스 추가 방법
Child1 = type('Child1', (Parent, ), {'name': 'jack', 'sex': ' '})
In [85]: Child2 = type('Child2', (Parent, ), {'name': 'mary', 'sex': ' '})
In [87]: Child1.name, Child1.sex
Out[87]: ('jack', ' ')
In [88]: Child2.name, Child2.sex
Out[88]: ('mary', ' ')
정적 방법 추가
In [96]: Parent = type('Parent', (), {'name': 'hui'})
In [97]: #
In [98]: @staticmethod
...: def test_static():
...: print('static method called...')
...:
In [100]: Child4 = type('Child4', (Parent, ), {'name': 'zhangsan', 'test_static': test_static})
In [101]: c4 = Child4()
In [102]: c4.test_static()
static method called...
In [103]: Child4.test_static()
static method called...
클래스 추가 방법
In [105]: Parent = type('Parent', (), {'name': 'hui'})
In [106]: #
In [107]: @classmethod
...: def test_class(cls):
...: print(cls.name)
...:
In [108]: Child5 = type('Child5', (Parent, ), {'name': 'lisi', 'test_class': test_class})
In [109]: c5 = Child5()
In [110]: c5.test_class()
lisi
In [111]: Child5.test_class()
lisi
파이썬에서 클래스도 대상이고 동적으로 클래스를 만들 수 있다는 것을 볼 수 있습니다.이것이 바로 당신이 키워드class
를 사용할 때Python
막후에서 하는 일이고 원류를 통해 이루어지는 것이다.비교적 완전하게 type을 사용하여 클래스를 만드는 방법:
class Animal(object):
def eat(self):
print(' ')
def dog_eat(self):
print(' ')
def cat_eat(self):
print(' ')
Dog = type('Dog', (Animal, ), {'tyep': ' ', 'eat': dog_eat})
Cat = type('Cat', (Animal, ), {'tyep': ' ', 'eat': cat_eat})
# ipython
In [125]: animal = Animal()
In [126]: dog = Dog()
In [127]: cat = Cat()
In [128]: animal.eat()
In [129]: dog.eat()
In [130]: cat.eat()
6. 도대체 무엇이 원류인가(드디어 주제에 이르렀다)
원류는 바로 종류를 만드는 데 쓰이는 것이다.당신이 클래스를 만드는 것은 클래스의 실례 대상을 만들기 위한 것이지 않습니까?하지만 우리는 파이썬의 클래스도 대상이라는 것을 배웠다.
메타클래스는 이러한 클래스(대상)를 만드는 데 사용되고, 메타클래스는 클래스의 클래스입니다. 당신은 다음과 같이 이해할 수 있습니다.
MyClass = MetaClass() # , “ ”
my_object = MyClass() # “ ”
이렇게 할 수 있는 type을 보았습니다.
MyClass = type('MyClass', (), {})
함수type
가 사실상 원류이기 때문이다.type
바로 파이썬이 뒤에서 모든 클래스를 만드는 데 사용하는 원류입니다.지금 궁금해요. 그런데 왜 타입은 타입이 아니라 소문자로 쓰입니까?알겠습니다. 이것은 str와 일치성을 유지하기 위해서입니다.str는 문자열 대상을 만드는 클래스이고, int는 정수 대상을 만드는 클래스입니다.type은 클래스 대상을 만드는 클래스입니다.너는 __class__
속성을 검사해서 이 점을 볼 수 있다.그래서 Python에서는 만물이 대상입니다.현재 어느
__class__
의__class__
속성에 대해서도 무엇일까요?
In [136]: a = 10
In [137]: b = 'acb'
In [138]: li = [1, 2, 3]
In [139]: a.__class__.__class__
Out[139]: type
In [140]: b.__class__.__class__
Out[140]: type
In [141]: li.__class__.__class__
Out[141]: type
In [142]: li.__class__.__class__.__class__
Out[142]: type
따라서 원류는 이런 대상을 만드는 것이다.type은 바로Python의 내장 원류입니다. 물론, 당신도 자신의 원류를 만들 수 있습니다.7. metaclass 속성
클래스를 정의할 때
__metaclass__
속성을 추가할 수 있습니다.
class Foo(object):
__metaclass__ = something…
... ...
만약 네가 이렇게 한다면, Python은 원류로 클래스 Foo를 만들 것이다.조심해, 이 안에 기교가 좀 있어.먼저 class Foo(object)
를 쓰십시오. 그러나 클래스 Foo는 메모리에 생성되지 않았습니다.파이썬은 클래스의 정의에서 __metaclass__
속성을 찾습니다. 찾으면 파이썬은 클래스 Foo를 만들고, 찾지 못하면 내장된 type
으로 클래스를 만듭니다.
class Foo(Bar):
pass
Python은 다음과 같은 작업을 수행했습니다.1. Foo에
__metaclass__
이 속성이 있습니까?있는 경우 파이썬은 __metaclass__
를 통해 Foo라는 클래스(객체)를 만듭니다.2. Python이
__metaclass__
를 찾지 못하면 Bar(부류)에서 __metaclass__
속성을 계속 찾고 앞과 같은 작업을 시도합니다.3. 만약 Python이 어떤 부류에서도 찾을 수 없다면
__metaclass__
, 모듈 차원에서 __metaclass__
을 찾고 같은 조작을 시도할 것이다.4. 만약
__metaclass__
를 찾지 못한다면, 파이썬은 내장된 type
으로 이 종류의 대상을 만들 것입니다.지금의 문제는
__metaclass__
에 어떤 코드를 놓을 수 있느냐는 것이다.답은 하나의 종류를 만들 수 있다는 것이다.그러면 어떤 종류를 만들 수 있습니까?type, 또는 type이나 하위 클래스화된 type에 사용할 수 있습니다.
8. 사용자 정의 클래스
원류의 주요 목적은 클래스를 만들 때 자동으로 클래스를 바꿀 수 있도록 하는 것이다.
바보 같은 예를 가상해 보세요. 모듈에 있는 모든 종류의 속성은 대문자 형식이어야 합니다.여러 가지 방법이 있지만 그 중 하나는 모듈 등급 설정
__metaclass__
을 통해 할 수 있다.이런 방법을 채택하면 이 모듈의 모든 종류는 이 원류를 통해 만들어진다. 우리는 원류에게 모든 속성을 대문자 형식으로 바꾸는 것만 알려주면 된다.다행히도
__metaclass__
실제로는 임의로 호출될 수 있으며, 정식 클래스가 필요하지 않다.그래서 우리는 여기서 간단한 함수를 예로 삼아 시작한다.python2 중
# -*- coding:utf-8 -*-
def upper_attr(class_name, class_parents, class_attr):
# class_name Foo
# class_parents object
# class_attr
# , __
new_attr = {}
for name, value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()] = value
# type
return type(class_name, class_parents, new_attr)
class Foo(object):
__metaclass__ = upper_attr # Foo upper_attr
bar = 'bip'
print(hasattr(Foo, 'bar'))
# Flase
print(hasattr(Foo, 'BAR'))
# True
f = Foo()
print(f.BAR)
python3 중
# -*- coding:utf-8 -*-
def upper_attr(class_name, class_parents, class_attr):
# , __
new_attr = {}
for name,value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()] = value
# type
return type(class_name, class_parents, new_attr)
# () metaclass
class Foo(object, metaclass=upper_attr):
bar = 'bip'
print(hasattr(Foo, 'bar'))
# Flase
print(hasattr(Foo, 'BAR'))
# True
f = Foo()
print(f.BAR)
다시 한 번, 이번에는 진정한 class
을 원류로 삼는다.
class UpperAttrMetaClass(type):
def __new__(cls, class_name, class_parents, class_attr):
# , __
new_attr = {}
for name, value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()] = value
# 1: 'type'
return type(class_name, class_parents, new_attr)
# 2: type.__new__
# OOP ,
# return type.__new__(cls, class_name, class_parents, new_attr)
# python3
class Foo(object, metaclass=UpperAttrMetaClass):
bar = 'bip'
# python2
class Foo(object):
__metaclass__ = UpperAttrMetaClass
bar = 'bip'
print(hasattr(Foo, 'bar'))
# : False
print(hasattr(Foo, 'BAR'))
# : True
f = Foo()
print(f.BAR)
# : 'bip'
__new__ __init__
__new__
__init__
, , , __new__
그렇습니다. 그 외에 원류에 관해서는 정말 더 이상 할 말이 없습니다.그러나 원류 자체로 말하자면 그것들은 사실 매우 간단하다.1. 차단 클래스 생성
2. 클래스 수정
3. 수정된 클래스 되돌리기
총결산
이제 우리의 큰 주제로 돌아가면 도대체 왜 당신은 이런 실수하기 쉽고 난삽한 특성을 사용합니까?
그래, 일반적으로 말하자면, 너는 전혀 그것을 사용할 수 없다.
"원류는 깊은 마법이다. 99퍼센트의 사용자들은 전혀 걱정할 필요가 없다. 원류를 사용해야 하는지 알고 싶다면 원류를 필요로 하지 않는다. 원류를 실제로 사용하는 사람들은 그들이 무엇을 해야 하는지 잘 알고 있으며, 왜 원류를 사용해야 하는지 설명할 필요가 없다."파이썬계의 리더 Tim Peters
파이썬 진급 학습에 관한 이 글은 파이썬 클래스의 원조-원류를 탐색하는 데 도움이 됩니다. 파이썬 원류에 대한 더 많은 내용은 저희 이전의 글을 검색하거나 아래의 관련 글을 계속 찾아보세요. 앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.