cython

Форк
0
/
dict_setdefault.py 
122 строки · 3.0 Кб
1

2
import cython
3

4
class Unhashable(object):
5
    def __hash__(self):
6
        raise TypeError('I am not hashable')
7

8
class Hashable(object):
9
    def __hash__(self):
10
        return 1
11
    def __eq__(self, other):
12
        return isinstance(other, Hashable)
13

14
class CountedHashable(object):
15
    def __init__(self):
16
        self.hash_count = 0
17
        self.eq_count = 0
18
    def __hash__(self):
19
        self.hash_count += 1
20
        return 42
21
    def __eq__(self, other):
22
        self.eq_count += 1
23
        return id(self) == id(other)
24

25
@cython.test_fail_if_path_exists('//AttributeNode')
26
@cython.test_assert_path_exists('//PythonCapiCallNode')
27
@cython.locals(d=dict)
28
def setdefault1(d, key):
29
    """
30
    >>> d = {}
31
    >>> setdefault1(d, 1)
32
    >>> len(d)
33
    1
34
    >>> setdefault1(d, 1)
35
    >>> len(d)
36
    1
37
    >>> d[1]
38
    >>> setdefault1(d, Unhashable())
39
    Traceback (most recent call last):
40
    TypeError: I am not hashable
41
    >>> len(d)
42
    1
43
    >>> h1 = setdefault1(d, Hashable())
44
    >>> len(d)
45
    2
46
    >>> h2 = setdefault1(d, Hashable())
47
    >>> len(d)
48
    2
49
    >>> d[Hashable()]
50

51
    # CPython's behaviour depends on version and py_debug setting, so just compare to it
52
    >>> py_hashed1 = CountedHashable()
53
    >>> y = {py_hashed1: 5}
54
    >>> py_hashed2 = CountedHashable()
55
    >>> y.setdefault(py_hashed2)
56

57
    >>> cy_hashed1 = CountedHashable()
58
    >>> y = {cy_hashed1: 5}
59
    >>> cy_hashed2 = CountedHashable()
60
    >>> setdefault1(y, cy_hashed2)
61
    >>> py_hashed1.hash_count - cy_hashed1.hash_count
62
    0
63
    >>> py_hashed2.hash_count - cy_hashed2.hash_count
64
    0
65
    >>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
66
    0
67
    """
68
    return d.setdefault(key)
69

70
@cython.test_fail_if_path_exists('//AttributeNode')
71
@cython.test_assert_path_exists('//PythonCapiCallNode')
72
@cython.locals(d=dict)
73
def setdefault2(d, key, value):
74
    """
75
    >>> d = {}
76
    >>> setdefault2(d, 1, 2)
77
    2
78
    >>> len(d)
79
    1
80
    >>> setdefault2(d, 1, 2)
81
    2
82
    >>> len(d)
83
    1
84
    >>> l = setdefault2(d, 2, [])
85
    >>> len(d)
86
    2
87
    >>> l.append(1)
88
    >>> setdefault2(d, 2, [])
89
    [1]
90
    >>> len(d)
91
    2
92
    >>> setdefault2(d, Unhashable(), 1)
93
    Traceback (most recent call last):
94
    TypeError: I am not hashable
95
    >>> h1 = setdefault2(d, Hashable(), 55)
96
    >>> len(d)
97
    3
98
    >>> h2 = setdefault2(d, Hashable(), 66)
99
    >>> len(d)
100
    3
101
    >>> d[Hashable()]
102
    55
103

104
    # CPython's behaviour depends on version and py_debug setting, so just compare to it
105
    >>> py_hashed1 = CountedHashable()
106
    >>> y = {py_hashed1: 5}
107
    >>> py_hashed2 = CountedHashable()
108
    >>> y.setdefault(py_hashed2, [])
109
    []
110

111
    >>> cy_hashed1 = CountedHashable()
112
    >>> y = {cy_hashed1: 5}
113
    >>> cy_hashed2 = CountedHashable()
114
    >>> setdefault2(y, cy_hashed2, [])
115
    []
116
    >>> py_hashed1.hash_count - cy_hashed1.hash_count
117
    0
118
    >>> py_hashed2.hash_count - cy_hashed2.hash_count
119
    0
120
    >>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
121
    0
122
    """
123
    return d.setdefault(key, value)
124

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.