1# test for correct binding of self when accessing attr of an instance
2
3class A:
4    def __init__(self, arg):
5        self.val = arg
6    def __str__(self):
7        return 'A.__str__ ' + str(self.val)
8    def __call__(self, arg):
9        return 'A.__call__', arg
10    def foo(self, arg):
11        return 'A.foo', self.val, arg
12
13def make_closure(x_in):
14    x = x_in
15    def closure(y):
16        return x, y is c
17    return closure
18
19class C:
20    # these act like methods and bind self
21
22    def f1(self, arg):
23        return 'C.f1', self is c, arg
24    f2 = lambda self, arg: ('C.f2', self is c, arg)
25    f3 = make_closure('f3') # closure
26    def f4(self, arg): # generator
27        yield self is c, arg
28
29    # these act like simple variables and don't bind self
30
31    f5 = int # builtin type
32    f6 = abs # builtin function
33    f7 = A # user type
34    f8 = A(8) # user instance which is callable
35    f9 = A(9).foo # user bound method
36
37c = C()
38print(c.f1(1))
39print(c.f2(2))
40print(c.f3())
41print(next(c.f4(4)))
42print(c.f5(5))
43print(c.f6(-6))
44print(c.f7(7))
45print(c.f8(8))
46print(c.f9(9))
47
48# test calling the functions accessed via the class itself
49print(C.f5(10))
50print(C.f6(-11))
51print(C.f7(12))
52print(C.f8(13))
53print(C.f9(14))
54
55# not working in uPy
56#class C(list):
57#    # this acts like a method and binds self
58#    f1 = list.extend
59#c = C()
60#c.f1([3, 1, 2])
61#print(c)
62