python 3: hook list & dict changes

  • Last Update :
  • Techknowledgy :

Subclassing dict maybe:

class DictWatch(dict):
   def __init__(self, * args, ** kwargs):
   self.callback = kwargs.pop('callback')
dict.__init__(self, args)

def __setitem__(self, key, val):
   # YOUR HOOK HERE
self.callback(key, val)
dict.__setitem__(self, key, val)

# and other overrided dict methods
if you need them

Demo:

>>> def cb(k, v):
   ...print k, v
   ...
   >>>
   d = DictWatch(callback = cb) >>>
   d['key'] = '100'
key 100

There's even more to that. Some built-in methods that receive a dictionary through argument will not call any overriden methods at all in CPython, as shown in the following example from PyPy wiki:

>>> > class D(dict):
   ....def __getitem__(self, key):
   ....return 42
   .... >>>
   >
   >>>
   > d1 = {} >>>
   > d2 = D(a = 'foo') >>>
   > d1.update(d2) >>>
   > print d1['a']
foo # but 42 in PyPy

Example for hooky.List:

#!/usr/bin/env python

from hooky
import List

class MyList(List):
   def _before_add(self, key, item):
   print('before add, key: {}, item: {}'.format(key, repr(item)))

def _after_add(self, key, item):
   print(' after add, key: {}, item: {}'.format(key, repr(item)))

def _before_del(self, key):
   print('before_del, key: ', key)

def _after_del(self, key):
   print(' after_del, key: ', key)

l = MyList(['a', 'b'])

l.append(1)

l.extend(['f', 'g', 2])

l.pop()

l[2: 3] = ['c', 'd', 'e']

print(l)

l.clear()

print(l)

print out:

before add, key: 0, item: 'a'
after add, key: 0, item: 'a'
before add, key: 1, item: 'b'
after add, key: 1, item: 'b'
before add, key: 2, item: 1
after add, key: 2, item: 1
before add, key: 3, item: 'f'
after add, key: 3, item: 'f'
before add, key: 4, item: 'g'
after add, key: 4, item: 'g'
before add, key: 5, item: 2
after add, key: 5, item: 2
before_del, key: -1
after_del, key: -1
before_del, key: 2
after_del, key: 2
before add, key: 2, item: 'c'
after add, key: 2, item: 'c'
before add, key: 3, item: 'd'
after add, key: 3, item: 'd'
before add, key: 4, item: 'e'
after add, key: 4, item: 'e' ['a', 'b', 'c', 'd', 'e', 'f', 'g']
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1[]

Suggestion : 2

So my question is: how do I hook mutators of anycodings_python-3.x given structures? Is there something I don't anycodings_python-3.x know?,Even though subclassing built-in classes anycodings_python-3.x is officially supported, I'd still anycodings_python-3.x recommend you consider using a proxy anycodings_python-3.x class.,There's even more to that. Some built-in anycodings_python-3.x methods that receive a dictionary anycodings_python-3.x through argument will not call any anycodings_python-3.x overriden methods at all in CPython, as anycodings_python-3.x shown in the following example from PyPy anycodings_python-3.x wiki:,Multiple key presses detected on SFML, can't solve it in any other way and works differently on different machines

There's even more to that. Some built-in anycodings_python-3.x methods that receive a dictionary anycodings_python-3.x through argument will not call any anycodings_python-3.x overriden methods at all in CPython, as anycodings_python-3.x shown in the following example from PyPy anycodings_python-3.x wiki:

>>> > class D(dict):
   ....def __getitem__(self, key):
   ....return 42
   .... >>>
   >
   >>>
   > d1 = {} >>>
   > d2 = D(a = 'foo') >>>
   > d1.update(d2) >>>
   > print d1['a']
foo # but 42 in PyPy

Subclassing dict maybe:

class DictWatch(dict):
   def __init__(self, * args, ** kwargs):
   self.callback = kwargs.pop('callback')
dict.__init__(self, args)

def __setitem__(self, key, val):
   # YOUR HOOK HERE
self.callback(key, val)
dict.__setitem__(self, key, val)

# and other overrided dict methods
if you need them

Demo:

>>> def cb(k, v):
   ...print k, v
   ...
   >>>
   d = DictWatch(callback = cb) >>>
   d['key'] = '100'
key 100

Example for hooky.List:

#!/usr/bin/env python

from hooky
import List

class MyList(List):
   def _before_add(self, key, item):
   print('before add, key: {}, item: {}'.format(key, repr(item)))

def _after_add(self, key, item):
   print(' after add, key: {}, item: {}'.format(key, repr(item)))

def _before_del(self, key):
   print('before_del, key: ', key)

def _after_del(self, key):
   print(' after_del, key: ', key)

l = MyList(['a', 'b'])

l.append(1)

l.extend(['f', 'g', 2])

l.pop()

l[2: 3] = ['c', 'd', 'e']

print(l)

l.clear()

print(l)

print out:

before add, key: 0, item: 'a'
after add, key: 0, item: 'a'
before add, key: 1, item: 'b'
after add, key: 1, item: 'b'
before add, key: 2, item: 1
after add, key: 2, item: 1
before add, key: 3, item: 'f'
after add, key: 3, item: 'f'
before add, key: 4, item: 'g'
after add, key: 4, item: 'g'
before add, key: 5, item: 2
after add, key: 5, item: 2
before_del, key: -1
after_del, key: -1
before_del, key: 2
after_del, key: 2
before add, key: 2, item: 'c'
after add, key: 2, item: 'c'
before add, key: 3, item: 'd'
after add, key: 3, item: 'd'
before add, key: 4, item: 'e'
after add, key: 4, item: 'e' ['a', 'b', 'c', 'd', 'e', 'f', 'g']
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1
before_del, key: -1
after_del, key: -1[]

Suggestion : 3

In type annotations you can now use built-in collection types such as list and dict as generic types instead of importing the corresponding capitalized types (e.g. List or Dict) from typing. Some other types in the standard library are also now generic, for example queue.Queue.,PEP 593 introduced an typing.Annotated type to decorate existing types with context-specific metadata and new include_extras parameter to typing.get_type_hints() to access the metadata at runtime. (Contributed by Till Varoquaux and Konstantin Kashin.),Previously, the bytecode evaluation loop was interrupted at each instruction until the main thread handles signals. (Contributed by Victor Stinner in bpo-40010.),Division handling of PurePath now returns NotImplemented instead of raising a TypeError when passed something other than an instance of str or PurePath. This allows creating compatible classes that don’t inherit from those mentioned types. (Contributed by Roger Aiudi in bpo-34775).

>>> x = {
      "key1": "value1 from x",
      "key2": "value2 from x"
   } >>>
   y = {
      "key2": "value2 from y",
      "key3": "value3 from y"
   } >>>
   x | y {
      'key1': 'value1 from x',
      'key2': 'value2 from y',
      'key3': 'value3 from y'
   } >>>
   y | x {
      'key2': 'value2 from x',
      'key3': 'value3 from y',
      'key1': 'value1 from x'
   }
def greet_all(names: list[str]) - > None:
   for name in names:
   print("Hello", name)
>>> from zoneinfo
import ZoneInfo
   >>>
   from datetime
import datetime, timedelta

   >>>
   # Daylight saving time >>>
   dt = datetime(2020, 10, 31, 12, tzinfo = ZoneInfo("America/Los_Angeles")) >>>
   print(dt)
2020 - 10 - 31 12: 00: 00 - 07: 00 >>>
   dt.tzname()
'PDT'

>>>
# Standard time
   >>>
   dt += timedelta(days = 7) >>>
   print(dt)
2020 - 11 - 07 12: 00: 00 - 08: 00 >>>
   print(dt.tzname())
PST
int
foo_traverse(foo_struct * self, visitproc visit, void * arg) {
   // Rest of the traverse function
   #if PY_VERSION_HEX >= 0x03090000
   // This was not needed before Python 3.9 (Python issue 35810 and 40217)
   Py_VISIT(Py_TYPE(self));
   #endif
}
base - > tp_traverse(self, visit, arg)

Suggestion : 4

You can use the built-in function enumerate() to obtain the positional indexes, when looping through a sequence. For example,,This example prompts user for a hexadecimal (hex) string, and print its decimal equivalent. It illustrates for-loop with index, nested-if, string operation and dictionary (associative array). For example,,Instead of using a for-in loop to iterate through all the items in an iterable (sequence), you can use the following functions to apply an operation to all the items. This is known as functional programming or expression-oriented programming. Filter-map-reduce is popular in big data analysis (or data science).,The range() function produces a series of running integers, which can be used as index list for the for-in loop.

{}
header_1: # Headers are terminated by a colon
statement_1_1 # Body blocks are indented(recommended to use 4 spaces)
statement_1_2
   ......
   header_2:
   statement_2_1
statement_2_2
   ......

   # You can place the body - block in the same line, separating the statement by semi - colon(;)
# This is NOT recommended.
header_1: statement_1_1;
statement_1_2;......
header_2: statement_2_1;
statement_2_2;......
Conditional
#
if -
else
if test: # no parentheses needed
for test
true_block
else: # Optional
false_block

# Nested -
   if
if test_1:
   block_1
elif test_2:
   block_2
   ......
   elif test_n:
   block_n
else:
   else_block

# Shorthand
if -
else
   true_expr
if test
else false_expr
Loop
#
while -do loop
while test: # no parentheses needed
for test
true_block
else: # Optional, run only
if no
break encountered
else_block

#
for -each loop
for item in sequence:
   true_block
else: # Optional, run only
if no
break encountered
else_block
Function Definition
def functionName( * args, ** kwargs): # Positional and keyword arguments
body
return return_vale
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88