mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
Issue #22955: attrgetter, itemgetter and methodcaller objects in the operator
module now support pickling. Added readable and evaluable repr for these objects. Based on patch by Josh Rosenberg.
This commit is contained in:
parent
5418d0bfc4
commit
35ac5f8280
4 changed files with 427 additions and 9 deletions
|
@ -231,10 +231,13 @@ class attrgetter:
|
|||
After h = attrgetter('name.first', 'name.last'), the call h(r) returns
|
||||
(r.name.first, r.name.last).
|
||||
"""
|
||||
__slots__ = ('_attrs', '_call')
|
||||
|
||||
def __init__(self, attr, *attrs):
|
||||
if not attrs:
|
||||
if not isinstance(attr, str):
|
||||
raise TypeError('attribute name must be a string')
|
||||
self._attrs = (attr,)
|
||||
names = attr.split('.')
|
||||
def func(obj):
|
||||
for name in names:
|
||||
|
@ -242,7 +245,8 @@ class attrgetter:
|
|||
return obj
|
||||
self._call = func
|
||||
else:
|
||||
getters = tuple(map(attrgetter, (attr,) + attrs))
|
||||
self._attrs = (attr,) + attrs
|
||||
getters = tuple(map(attrgetter, self._attrs))
|
||||
def func(obj):
|
||||
return tuple(getter(obj) for getter in getters)
|
||||
self._call = func
|
||||
|
@ -250,19 +254,30 @@ class attrgetter:
|
|||
def __call__(self, obj):
|
||||
return self._call(obj)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s.%s(%s)' % (self.__class__.__module__,
|
||||
self.__class__.__qualname__,
|
||||
', '.join(map(repr, self._attrs)))
|
||||
|
||||
def __reduce__(self):
|
||||
return self.__class__, self._attrs
|
||||
|
||||
class itemgetter:
|
||||
"""
|
||||
Return a callable object that fetches the given item(s) from its operand.
|
||||
After f = itemgetter(2), the call f(r) returns r[2].
|
||||
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])
|
||||
"""
|
||||
__slots__ = ('_items', '_call')
|
||||
|
||||
def __init__(self, item, *items):
|
||||
if not items:
|
||||
self._items = (item,)
|
||||
def func(obj):
|
||||
return obj[item]
|
||||
self._call = func
|
||||
else:
|
||||
items = (item,) + items
|
||||
self._items = items = (item,) + items
|
||||
def func(obj):
|
||||
return tuple(obj[i] for i in items)
|
||||
self._call = func
|
||||
|
@ -270,6 +285,14 @@ class itemgetter:
|
|||
def __call__(self, obj):
|
||||
return self._call(obj)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s.%s(%s)' % (self.__class__.__module__,
|
||||
self.__class__.__name__,
|
||||
', '.join(map(repr, self._items)))
|
||||
|
||||
def __reduce__(self):
|
||||
return self.__class__, self._items
|
||||
|
||||
class methodcaller:
|
||||
"""
|
||||
Return a callable object that calls the given method on its operand.
|
||||
|
@ -277,6 +300,7 @@ class methodcaller:
|
|||
After g = methodcaller('name', 'date', foo=1), the call g(r) returns
|
||||
r.name('date', foo=1).
|
||||
"""
|
||||
__slots__ = ('_name', '_args', '_kwargs')
|
||||
|
||||
def __init__(*args, **kwargs):
|
||||
if len(args) < 2:
|
||||
|
@ -284,12 +308,30 @@ class methodcaller:
|
|||
raise TypeError(msg)
|
||||
self = args[0]
|
||||
self._name = args[1]
|
||||
if not isinstance(self._name, str):
|
||||
raise TypeError('method name must be a string')
|
||||
self._args = args[2:]
|
||||
self._kwargs = kwargs
|
||||
|
||||
def __call__(self, obj):
|
||||
return getattr(obj, self._name)(*self._args, **self._kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
args = [repr(self._name)]
|
||||
args.extend(map(repr, self._args))
|
||||
args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items())
|
||||
return '%s.%s(%s)' % (self.__class__.__module__,
|
||||
self.__class__.__name__,
|
||||
', '.join(args))
|
||||
|
||||
def __reduce__(self):
|
||||
if not self._kwargs:
|
||||
return self.__class__, (self._name,) + self._args
|
||||
else:
|
||||
from functools import partial
|
||||
return partial(self.__class__, self._name, **self._kwargs), self._args
|
||||
|
||||
|
||||
# In-place Operations *********************************************************#
|
||||
|
||||
def iadd(a, b):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue