forked from ElectricRCAircraftGuy/eRCaGuy_hello_world
-
Notifications
You must be signed in to change notification settings - Fork 0
/
slots_practice.py
executable file
·200 lines (156 loc) · 6.86 KB
/
slots_practice.py
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/python3
# This file is part of eRCaGuy_hello_world: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world
"""
GOAL:
Learn a little bit about the special Python `__slots__` list, class variables vs. instance
variables, private variables vs public variables, and internal Python variables surrounded by double
underscores (`__some_var__`). Also practice passing and using list args to a function (ex: as
`*args`), and keyword key:value dict args to a function as well (ex: as `**kwargs`).
PYTHON DEFINITIONS:
1. Variables prefixed with a single underscore (`_`) are user-specific **private variables**.
All other variables (NOT beginning with `_`) are therefore, by default, **public variables**.
Ex:
```
_my_private_var = 123
# vs:
my_public_var = 123
```
1. Variables which begin and end with two underscores (`__some_name__`) are **internal Python
variables** used by the Python interpreter/language. Ex: `__slots__`, `__name__`, `__main__`.
1. Variables outside of all methods inside a class are **class variables**. They are shared among
all objects (instances) of a given class. You can access them inside the class definition in 2 ways:
```
MyClass.class_var
self.class_var
```
...and outside the class definition directly as well, so long as they are public, NOT private
variables. Ex:
```
myClass = MyClass()
myClass.class_var
```
1. Variables inside any class method and which are prefixed with `self.` are **instance variables**.
They have unique values for each instance of a class. For classes which do NOT use the `__slots__`
internal variable shown below, these "instance variables" are stored via a key:value dict, with each
key being the name of the variable (stored and accessed as a _string_). When you use the special
`__slots__` variable manually, however, you can save run-time RAM by having Python store these
instance variable names in a list instead of in a dict!
RUN COMMAND:
./slots_practice.py
# OR
python3 slots_practice.py
REFERENCES:
1. Slots: https://book.pythontips.com/en/latest/__slots__magic.html
1. Class vs Instance variables: https://realpython.com/lessons/class-and-instance-attributes/
1. Official Python `__slots__` documentation:
https://docs.python.org/3/reference/datamodel.html?highlight=__slots__#slots
1. [NEED TO STUDY AND READ STILL] https://stackoverflow.com/questions/472000/usage-of-slots
"""
import textwrap
class MyClass():
# 1. Class variables (shared among all instances of this class--must be defined outside all other
# class methods)
# arbitrary variable I made up
animal = "dragon"
# Count how many instances of this class have been created.
# See: https://stackoverflow.com/a/47610553/4561887
instance_counter = 0
# special list of all string names of our instance variables
# __slots__ = ['var1', 'var2'] # <======== does NOT work because it doesn't define 'var3' which we use and need below too!
__slots__ = ['var1', 'var2', 'var3'] # <======== WORKS!
# arbitrarily-named, private (prefixed with single `_`) list of the types (stored as strings)
# for the instance variables specified above
_slot_types = ['string', 'int', 'list of ints']
def __init__(self, *args, **kwargs):
"""
Constructor to create a new MyClass instance.
Parameters:
*args: special syntax to capture a list of all list arguments
**kwargs: special syntax to capture a dict of all keyword arguments passed in as
key:value pairs (written as `someFunc(key1 = value1, key2 = value2)`
when you call the method).
Returns:
NA
"""
MyClass.instance_counter += 1
# 2. Instance variables (begin with `self.`--these can be defined and/or accessed within ANY
# method within a class!):
self.var1 = kwargs['var1']
self.var2 = kwargs['var2']
self.var3 = kwargs['var3']
print("MyClass.instance_counter = {}".format(MyClass.instance_counter))
if (MyClass.instance_counter == 1):
print(textwrap.dedent('''\
Note to self: to pass in the args list and the dict to another func as if you typed them into the
function directly, it would look like this:
func(*args)
# and
func2(**kwargs)
'''))
print("Here are all the dictionary items you passed in!:")
print("args = {}".format(args))
print("kwargs = {}".format(kwargs))
for key, value in kwargs.items():
print(" {}: {}".format(key, value))
def printVariables(self):
"""
Print all class and instance variables for this class.
"""
print("Class variables:")
print(" animal (MyClass.animal) = {}".format(MyClass.animal))
print(" animal (self.animal) = {}".format(self.animal)) # alternative way
print("Instance variables:")
print(" self.var1 = {}".format(self.var1))
print(" self.var2 = {}".format(self.var2))
print(" self.var3 = {}".format(self.var3))
if __name__ == '__main__':
"""
This runs only if you run this file directly, NOT if you import this file as a module into
another Python program. That is what this `if` statement does for us here!
"""
print("instance1:")
instance1 = MyClass(var1 = "hello", var2 = 710, var3 = [1, 2, 3])
instance1.printVariables()
print()
print("instance2:")
instance2 = MyClass(var1 = "world", var2 = 18, var3 = [4, 5, 6])
instance2.printVariables()
"""
SAMPLE OUTPUT:
$ slots_practice/slots_practice.py
instance1:
MyClass.instance_counter = 1
Note to self: to pass in the args list and the dict to another func as if you typed them into the
function directly, it would look like this:
func(*args)
# and
func2(**kwargs)
Here are all the dictionary items you passed in!:
args = ()
kwargs = {'var1': 'hello', 'var2': 710, 'var3': [1, 2, 3]}
var1: hello
var2: 710
var3: [1, 2, 3]
Class variables:
animal (MyClass.animal) = dragon
animal (self.animal) = dragon
Instance variables:
self.var1 = hello
self.var2 = 710
self.var3 = [1, 2, 3]
instance2:
MyClass.instance_counter = 2
Here are all the dictionary items you passed in!:
args = ()
kwargs = {'var1': 'world', 'var2': 18, 'var3': [4, 5, 6]}
var1: world
var2: 18
var3: [4, 5, 6]
Class variables:
animal (MyClass.animal) = dragon
animal (self.animal) = dragon
Instance variables:
self.var1 = world
self.var2 = 18
self.var3 = [4, 5, 6]
"""