객체 공간(object space)¶
Contents
소개¶
객체 공간(object space)은 PyPy에서 모든 객체를 생성하며, 그 객체에 대한 연산을 수행하는 방법을 알고 있습니다. 객체 공간(object space)을 고정된 API, 즉 Python 객체의 알려진 의미론에 대응하는 구현과 함께 하는 일련의 연산을 제공하는 라이브러리로 생각하면 도움이 될 수 있습니다.
예를 들어, add()는 연산이며, 객체 공간(object space)에는 (add()가 숫자에 대해 동작할 때는) 숫자 덧셈을, (add()가 시퀀스에 대해 동작할 때는) 연결(concatenation)을 수행하는 등의 구현들이 있습니다.
바이트코드 인터프리터에 연결될 수 있는 몇 가지 작동하는 객체 공간(object space)이 있습니다:
- 표준 객체 공간(object space)은 파이썬의 다양한 내장 타입과 객체에 대한 완전한 구현입니다. 표준 객체 공간(object space)은 바이트코드 인터프리터와 함께 우리 파이썬 구현의 기반입니다. 내부적으로 이것은 정수, 문자열, 리스트, 타입 등 다양한 application-level 객체를 구현하는 interpreter-level 클래스의 집합입니다. CPython과 비교하자면, 표준 객체 공간(object space)은 C 구조체
PyIntObject,PyListObject등에 상응하는 것을 제공합니다. - 다양한 객체 공간(object space) 프록시는 다른 객체 공간(object space)(예: 표준 객체 공간)을 감싸고, 지연 계산 객체(연산이 수행될 때만 계산되는 객체), 보안 검사 객체, 여러 기계에 분산되어 있는 분산 객체 등과 같은 새로운 기능을 추가합니다.
여기에 문서화된 다양한 객체 공간(object space)들은 pypy/objspace에서 찾을 수 있습니다.
대부분의 객체 공간(object space) 연산은 application-level 객체를 받아 반환하며, 인터프리터는 이 객체를 불투명한 “블랙박스”로 취급합니다. 극히 일부 연산만이 바이트코드 인터프리터가 application-level 객체의 값에 대해 어느 정도 알 수 있게 해줍니다.
객체 공간(object space) 인터페이스¶
이것은 모든 객체 공간(object space)이 구현하는 공개 API입니다:
관리 함수¶
-
getexecutioncontext()¶ Return the currently active execution context. (pypy/interpreter/executioncontext.py).
-
getbuiltinmodule(name)¶ Return a
Moduleobject for the built-in module given byname. (pypy/interpreter/module.py).
객체 공간(object space)의 객체에 대한 연산¶
이 함수들은 “래핑된”(즉, application-level) 객체를 받고 반환합니다.
다음 함수들은 언어 수준 구문에 직접 대응하는, 명확한 의미를 가진 연산을 구현합니다:
id, type, issubtype, iter, next, repr, str, len, hash,
getattr, setattr, delattr, getitem, setitem, delitem,
pos, neg, abs, invert, add, sub, mul, truediv, floordiv, div, mod, divmod, pow, lshift, rshift, and_, or_, xor,
nonzero, hex, oct, int, float, long, ord,
lt, le, eq, ne, gt, ge, cmp, coerce, contains,
inplace_add, inplace_sub, inplace_mul, inplace_truediv, inplace_floordiv, inplace_div, inplace_mod, inplace_pow, inplace_lshift, inplace_rshift, inplace_and, inplace_or, inplace_xor,
get, set, delete, userdel
-
call(w_callable, w_args, w_kwds)¶ Calls a function with the given positional (
w_args) and keyword (w_kwds) arguments.
-
index(w_obj)¶ Implements index lookup (as introduced in CPython 2.5) using
w_obj. Will return a wrapped integer or long, or raise aTypeErrorif the object doesn’t have an__index__()special method.
-
is_(w_x, w_y)¶ Implements
w_x is w_y.
-
isinstance(w_obj, w_type)¶ Implements
issubtype()withtype(w_obj)andw_typeas arguments.
편의 함수¶
다음 함수들은 매우 자주 사용되어서 단축 표현으로 도입할 가치가 있었습니다. 다만, 다른 여러 객체 공간(object space) 메서드를 사용하여 표현할 수 있으므로 반드시 필요한 것은 아닙니다.
-
eq_w(w_obj1, w_obj2)¶ Returns
Truewhenw_obj1andw_obj2are equal. Shortcut forspace.is_true(space.eq(w_obj1, w_obj2)).
-
is_w(w_obj1, w_obj2)¶ Shortcut for
space.is_true(space.is_(w_obj1, w_obj2)).
-
hash_w(w_obj)¶ Shortcut for
space.int_w(space.hash(w_obj)).
-
len_w(w_obj)¶ Shortcut for
space.int_w(space.len(w_obj)).
위 네 함수가 application-level 객체가 아니라 interpreter-level 객체를 반환한다는 점에 주의하십시오!
-
not_(w_obj)¶ Shortcut for
space.newbool(not space.is_true(w_obj)).
-
finditem(w_obj, w_key)¶ Equivalent to
getitem(w_obj, w_key)but returns an interpreter-level None instead of raising a KeyError if the key is not found.
-
call_function(w_callable, *args_w, **kw_w)¶ Collects the arguments in a wrapped tuple and dict and invokes
space.call(w_callable, ...).
-
call_method(w_object, 'method', ...)¶ Uses
space.getattr()to get the method object, and thenspace.call_function()to invoke it.
-
unpackiterable(w_iterable[, expected_length=-1])¶ Iterates over
w_x(usingspace.iter()andspace.next()) and collects the resulting wrapped objects in a list. Ifexpected_lengthis given and the length does not match, raises an exception.Of course, in cases where iterating directly is better than collecting the elements in a list first, you should use
space.iter()andspace.next()directly.
-
unpacktuple(w_tuple[, expected_length=None])¶ Equivalent to
unpackiterable(), but only for tuples.
-
callable(w_obj)¶ Implements the built-in
callable().
애플리케이션 레벨 객체 생성¶
-
wrap(x)¶ Deprecated! Eventually this method should disappear. Returns a wrapped object that is a reference to the interpreter-level object
x. This can be used either on simple immutable objects (integers, strings, etc.) to create a new wrapped object, or on instances ofW_Rootto obtain an application-level-visible reference to them. For example, most classes of the bytecode interpreter subclassW_Rootand can be directly exposed to application-level code in this way - functions, frames, code objects, etc.
-
newint(i)¶ Creates a wrapped object holding an integral value.
newintcreates an object of typeW_IntObject.
-
newlong(l)¶ Creates a wrapped object holding an integral value. The main difference to
newintis the type of the argument (which isrpython.rlib.rbigint.rbigint). On PyPy3 this method will return anint(PyPy2 it returns along).
-
newbytes(t)¶ The given argument is a rpython bytestring. Creates a wrapped object of type
bytes(both on PyPy2 and PyPy3).
-
newtext(t)¶ The given argument is a rpython bytestring. Creates a wrapped object of type
str. On PyPy3 this will return a wrapped unicode object. The object will hold a utf-8-nosg decoded value of t. The “utf-8-nosg” codec used here is slightly different from the “utf-8” implemented in Python 2 or Python 3: it is defined as utf-8 without any special handling of surrogate characters. They are encoded using the same three-bytes sequence that encodes any char in the range from'\u0800'to'\uffff'.PyPy2 will return a bytestring object. No encoding/decoding steps will be applied.
-
newbool(b)¶ Creates a wrapped
boolobject from an interpreter-level object.
-
newtuple([w_x, w_y, w_z, ...])¶ Creates a new wrapped tuple out of an interpreter-level list of wrapped objects.
-
newlist([..])¶ Creates a wrapped
listfrom an interpreter-level list of wrapped objects.
-
newdict()¶ Returns a new empty dictionary.
-
newslice(w_start, w_end, w_step)¶ Creates a new slice object.
-
newunicode(ustr)¶ Creates a Unicode string from an rpython unicode string. This method may disappear soon and be replaced by :py:function:`newutf8`.
-
newutf8(bytestr)¶ Creates a Unicode string from an rpython byte string, decoded as “utf-8-nosg”. On PyPy3 it is the same as :py:function:`newtext`.
더 많은 공간(space) 연산은 pypy/interpreter/baseobjspace.py와 pypy/objspace/std/objspace.py에서 찾을 수 있습니다.
애플리케이션 레벨에서 인터프리터 레벨로의 변환¶
-
unwrap(w_x)¶ Returns the interpreter-level equivalent of
w_x– use this ONLY for testing, because this method is not RPython and thus cannot be translated! In most circumstances you should use the functions described below instead.
-
is_true(w_x)¶ Returns an interpreter-level boolean (
TrueorFalse) that gives the truth value of the wrapped objectw_x.This is a particularly important operation because it is necessary to implement, for example, if-statements in the language (or rather, to be pedantic, to implement the conditional-branching bytecodes into which if-statements are compiled).
-
int_w(w_x)¶ If
w_xis an application-level integer or long which can be converted without overflow to an integer, return an interpreter-level integer. Otherwise raiseTypeErrororOverflowError.
-
bigint_w(w_x)¶ If
w_xis an application-level integer or long, return an interpreter-levelrbigint. Otherwise raiseTypeError.
-
ObjSpace.bytes_w(w_x)¶ Takes an application level
bytes(on PyPy2 this equals str) and returns a rpython byte string.
-
ObjSpace.text_w(w_x)¶ PyPy2 takes either a
strand returns a rpython byte string, or it takes anunicodeand uses the systems default encoding to return a rpython byte string.On PyPy3 it takes a
strand it will return an utf-8 encoded rpython string.
-
str_w(w_x)¶ Deprecated. use text_w or bytes_w instead If
w_xis an application-level string, return an interpreter-level string. Otherwise raiseTypeError.
-
unicode_w(w_x)¶ Takes an application level
unicodeand return an interpreter-level unicode string. This method may disappear soon and be replaced by :py:function:`text_w`.
-
float_w(w_x)¶ If
w_xis an application-level float, integer or long, return an interpreter-level float. Otherwise raiseTypeError(or:py:exc:OverflowError in the case of very large longs).
-
getindex_w(w_obj[, w_exception=None])¶ Call
index(w_obj). If the resulting integer or long object can be converted to an interpreter-levelint, return that. If not, return a clamped result ifw_exceptionis None, otherwise raise the exception at the application level.(If
w_objcan’t be converted to an index,index()will raise an application-levelTypeError.)
-
interp_w(RequiredClass, w_x[, can_be_None=False])¶ If
w_xis a wrapped instance of the given bytecode interpreter class, unwrap it and return it. Ifcan_be_NoneisTrue, a wrappedNoneis also accepted and returns an interpreter-levelNone. Otherwise, raises anOperationErrorencapsulating aTypeErrorwith a nice error message.
-
interpclass_w(w_x)¶ If
w_xis a wrapped instance of an bytecode interpreter class – for exampleFunction,Frame,Cell, etc. – return it unwrapped. Otherwise returnNone.
데이터 멤버¶
-
space.builtin¶ The
Modulecontaining the builtins.
-
space.sys¶ The
sysModule.
-
space.w_None¶ The ObjSpace’s instance of
None.
-
space.w_True¶ The ObjSpace’s instance of
True.
-
space.w_False¶ The ObjSpace’s instance of
False.
-
space.w_Ellipsis¶ The ObjSpace’s instance of
Ellipsis.
-
space.w_NotImplemented¶ The ObjSpace’s instance of
NotImplemented.
-
space.w_int¶ -
space.w_float¶ -
space.w_long¶ -
space.w_tuple¶ -
space.w_str¶ -
space.w_unicode¶ -
space.w_type¶ -
space.w_instance¶ -
space.w_slice¶ Python’s most common basic type objects.
-
space.w_[XYZ]Error Python’s built-in exception classes (
KeyError,IndexError, etc).
-
ObjSpace.MethodTable¶ List of tuples containing
(method_name, symbol, number_of_arguments, list_of_special_names)for the regular part of the interface.NOTE that tuples are interpreter-level.
-
ObjSpace.BuiltinModuleTable¶ List of names of built-in modules.
-
ObjSpace.ConstantTable¶ List of names of the constants that the object space should define.
-
ObjSpace.ExceptionTable¶ List of names of exception classes.
-
ObjSpace.IrregularOpTable¶ List of names of methods that have an irregular API (take and/or return non-wrapped objects).
표준 객체 공간(object space)¶
소개¶
표준 객체 공간(object space)(pypy/objspace/std/)은 CPython의 객체 라이브러리(배포판의 Objects/ 하위 디렉터리)에 직접 대응합니다. 이는 공통 파이썬 타입들을 더 낮은 수준의 언어로 구현한 것입니다.
표준 객체 공간(object space)은 추상 부모 클래스인 W_Object뿐만 아니라 W_IntObject, W_ListObject 등과 같은 하위 클래스도 정의합니다. 래핑된 객체(바이트코드 인터프리터의 메인 루프에게는 “블랙박스”)는 이 클래스들 중 하나의 인스턴스입니다. 메인 루프가 두 래핑된 객체 w1과 w2 사이에서 (덧셈과 같은) 연산을 호출하면, 표준 객체 공간(object space)은 (CPython의Object/abstract.c와 유사한) 내부 디스패치를 수행하고, 해당 연산을 수행할 수 있는 적절한 W_XYZObject 클래스의 메서드를 호출합니다.
연산 자체는 RPython이 허용하는 기본 연산(primitive)으로 수행되며, 결과는 래핑된(wrapped) 객체로 구성됩니다. 예를 들어, 다음의 정수 덧셈 구현을 Object/intobject.c안의 int_add() 함수와 비교해 보십시오:
def add__Int_Int(space, w_int1, w_int2):
x = w_int1.intval
y = w_int2.intval
try:
z = ovfcheck(x + y)
except OverflowError:
raise FailedToImplementArgs(space.w_OverflowError,
space.wrap("integer addition"))
return W_IntObject(space, z)
정수 객체만을 위해 이렇게 많은 작업을 하는 것처럼 보일 수도 있습니다(왜 일반 정수를 사용하는 대신 W_IntObject 인스턴스로 감싸는 걸까요?), 하지만 모든 객체(단순한 정수부터 더 복잡한 타입까지)를 동일한 방식으로 감쌈으로써 코드는 단순하고 읽기 쉽게 유지됩니다.
(흥미롭게도, 위의 명백한 최적화는 실제로 PyPy에서 이루어졌지만, 이 수준에서 하드코딩되어 있지는 않습니다 – 표준 인터프리터 최적화를 참조하십시오.)
객체 타입¶
대부분의 pypy/objspace/std/ 패키지 코드는 파이썬의 표준 내장 객체 타입 라이브러리를 정의하고 구현합니다. 각 타입 xxx (int, float, list, tuple, str, type 등)은 일반적으로 xxxobject.py 모듈에서 구현됩니다.
W_AbstractXxxObject클래스는 존재하는 경우 추상 베이스 클래스이며, 주로 Python 레벨 타입 객체에 나타나는 것을 정의합니다. 그런 다음 서브클래스로서 실제 구현체들이 있는데, 여러 다른 구현체가 있는 경우에는 W_XxxObject또는 그 변형으로 불립니다. 예를 들어, pypy/objspace/std/bytesobject.py는 str앱 레벨 타입을 만드는 데 필요한 모든 것을 담고 있는 W_AbstractBytesObject를 정의합니다. 그리고 서브클래스로 W_BytesObject (일반적인 문자열)와 W_Buffer (반복적인 추가에 맞춰 조정된 특수 구현으로, pypy/objspace/std/bufferobject.py에 있음)가 있습니다. 리스트나 딕셔너리와 같은 가변 데이터 타입의 경우, 실제 데이터에 대한 간접 참조와 전략(strategy)을 가진 단일 클래스 W_ListObject또는 W_DictMultiObject가 있습니다. 이 전략은 객체의 내용이 변경됨에 따라 바뀔 수 있습니다.
사용자 관점에서 볼 때, W_AbstractXxxObject 하위 클래스가 여러 개 있더라도 이는 보이지 않습니다: 앱 레벨에서는 여전히 모두 정확히 동일한 Python 타입의 인스턴스입니다. PyPy는 (예를 들어) 인터프리터 레벨의 W_BytesObject 인스턴스의 애플리케이션 레벨 타입이 str이라는 것을 알고 있는데, 이는 W_BytesObject에 pypy/objspace/std/bytesobject.py의 문자열 타입 명세를 가리키는 typedef 클래스 속성이 있기 때문입니다; 문자열의 다른 모든 구현체도 pypy/objspace/std/bytesobject.py의 동일한 typedef를 사용합니다.
동일한 Python 타입에 대한 여러 구현의 다른 예시는 표준 인터프리터 최적화를 참고하십시오.
객체 공간(object space) 프록시¶
우리는 다른 객체 공간(일반적으로 표준 객체 공간)을 감싸 모든 객체에 몇 가지 기능을 추가하는 여러 프록시 객체 공간(object space)들을 구현했습니다. 더 알아보려면 투명 프록시 (사용 중단됨)를 참고하십시오.