Hello. I'm Nabeta, who is a software engineer in the infrastructure group. It's the night of the 11th (22:00), so I'm writing this article quite impatiently. I will continue to write after finding it until the last minute. Hit the keyboard as calmly as you don't have time, Luke.
Basically, the release does not wait except when it is quite dangerous, so I think that everyone has experience in the case of sending it out to the world as "No!". Also, I couldn't take the time to refactor including the existing code, or I wrote a strange code because of my lack of ability. After that, I will reflect on some of the patterns that I have fixed. Anyway, I don't have time, so I'll do my best to fill the space for articles!
sample1.py
class Api(object):
def __init__(self, init_data):
self.init_data = init_data
self.prepare()
def prepare(self)
for k, v in self.init_data.items():
self.__data__[k] = v
ʻInit_data is a dictionary. Even if the inside of ʻinit_data
that is eaten by ʻApi is changed, I do not have to change the implementation of ʻApi
, and I often used it while thinking that it was metaprogramming and cool. If you read it, you have to know the internal implementation of ʻinit_data, and other classes and methods that implement using ʻApi
objects, which is quite painful. If you generate ʻinit_data` in code, it will be really unpleasant to read.
It was easier to read later if I prepared a dictionary that defined all key and value, or created a class that wraps it.
sample2.py
class Api(object):
def __init__(self, init_data):
self.name = name
self.a = init_data['a']
self.b = init_data['b']
...
Python allows you to put ʻelse` after a block of loops.
sample3.py
for i in range(5):
print('Count %d' % i)
else:
print('ELSE BLOCK!!')
This is executed immediately after the loop ends. There is no feeling of ʻelseat all. Furthermore, this one is skipped when
break is done, so I don't understand the meaning of ʻelse
anymore.
sample4.py
>>> for i in range(5):
... if i == 3:
... break
... print(i)
... else:
... print('ELSE!') # unreachable!
0
1
2
Then I was wondering what this guy was for, but I think it would be a little effective when processing something that meets the conditions in a loop. However, in that case, it is easier to read if you create a function for that. The name ʻelse` is misleading and should not be used.
The following is the one that scans and returns the result of whether or not the one you were looking for was found.
sample5.py
#This is better
def power_up_if(users):
found = False
for user in users:
if user == 42: #Return as soon as the condition you are looking for is found
found = True
break
return user, found
users = [1,2,3,41,42,5]
uid, found = power_up_if(users)
if found:
print('uid:', uid, 'is power up!')
You will rarely want to use non-static keyword arguments as default values for functions and methods.
sample6.py
>>> def log_out(msg, when=datetime.datetime.now()):
... print('%s %s ' % (when, msg))
...
... log_out('Good bye!!')
... log_out('Good bye!!')
2016-12-11 21:21:20.928785 Good bye!!
2016-12-11 21:21:20.928785 Good bye!!
I think this is a specification that you will surely know (step on) if you write Python as it is. The default argument is evaluated only once when the function is defined. That is, the value of the default argument is determined when the module is loaded and will never be evaluated again. I have also stepped on this specification and paid a lot of money to solve the problem. As a workaround
sample7.py
>>> def log_out(msg, when=None):
... """Output the log including the time stamp
...
... Args:
... msg:Log message
... when:Date and time of log output. If not, set the current date and time.
... """
... when = datetime.datetime.now() if when is None else when
... print('%s %s ' % (when, msg))
>>> log_out('hoge')
2016-12-11 21:28:58.293714 hoge
>>> log_out('bye')
2016-12-11 21:29:02.566320 bye
>>> log_out('bye', datetime.datetime(2016,11,1))
2016-11-01 00:00:00 bye
I think it's better to set the value of the default argument to None
and determine it by the idiom of when = datetime.datetime.now () if when is None else when
in the function. If there is, I will set it, and if not, I will do it here.
As far as I know, there is no absolute private in Python.
sample8.py
>>> class A(object):
... def __aa(self):
... print('private')
>>>
>>>
>>> a = A()
>>> a._A__aa()
private
>>> class A(object):
... def __init__(self, a):
... self.__a = a
>>>
>>> a = A(123)
>>> print(a.__dict__)
{'_A__a': 123}
So anyone who knows the above compiler conversion rules can access private attributes. However, since private and public exist as the visibility of the class, there is no case where the above access is actually required, and if so, I think that I made a mistake in the design.
Then, the reason why everyone can access public like is that it is already based on the theory of sexuality. I'm wondering if that's what Python is so cute, but you probably think that the benefits of being public are higher than the benefits of being private. I'm not sure if this is correct, but lately the cases of making it private (giving the __start attribute) are mostly limited to:
--Being a parent class --The namespace is likely to conflict in a small class --name, val, etc.
sample9.py
>>> class Student(object):
... def __init__(self):
... self.__name = "Anonymous"
...
... def get_name(self):
... return self.__name
...
... class ChildStudent(Student):
... def __init__(self):
... super().__init__()
... self._name = "Child"
...
... c = ChildStudent()
... print(c.get_name(), c._name)
Anonymous Child
This is by no means evil or anything like that, and you don't have to explicitly implement getters or setters.
sample10.py
>>> class OtherLangStyle(object):
... def __init__(self, val):
... self._val = val
...
... def get_val(self):
... return self._val
...
... def set_val(self, new_val):
... self._val = new_val
>>> ols = OtherLangStyle(1)
>>> ols.get_val()
1
>>> ols.set_val(2)
>>> ols.get_val()
2
>>> ols.set_val(ols.get_val() + 2)
>>> ols.get_val()
4
Not like Python. I feel like it's encapsulated. .. .. As mentioned above, I think that there is no problem if I simply implement it in public, and I always implement it in public.
sample11.py
>>> class PythonStyle(object):
... def __init__(self, val):
... self.val = val
... ps = PythonStyle(1)
... ps.val = 3
>>> ps.val
3
>>> ps.val += 4
>>> ps.val
7
If you need a hook later, Python has a super useful thing called a @property
decorator, and you can just implement @property
, setter.
sample12.py
>>> class Student(object):
... def __init__(self, name, score):
... self._name = name
... self._score = score
...
... @property
... def score(self):
... return self._score
...
... @score.setter
... def score(self, score):
... before = self.score
... self._score = score
... self.notify_score_up(before)
...
... @property
... def name(self):
... return self._name
...
... def notify_score_up(self, before):
... print('%s score is up. %d to %d.' %
... (self.name, before, self.score))
...
... s = Student('nabetama', 0)
... s.score = 3
nabetama score is up. 0 to 3.
By implementing the setter like this, you can also check the passed value!
When writing Python, everyone wants to write a decorator at least once. When you want to know the processing time of a function, etc.
sample13.py
>>> def checktime(func):
... @wraps(func)
... def wrapper(*args, **kwargs):
... import time
... start = time.time()
... res = func(*args, **kwargs)
... end = time.time() - start
... print('--------------------------------------------------')
... print(end)
... print('--------------------------------------------------')
... return res
... return wrapper
...
... @checktime
... def wait1():
... time.sleep(1)
... print('owata')
...
... wait1()
owata
... print(wait1)
<function wait1 at 0x1119a0d90> #wait1 and its metadata are returned
--------------------------------------------------
1.003669023513794
--------------------------------------------------
I prepare a decorator like this and do something like wrapping a function. The reason for using functools.wraps
is that the value (that is, the function) returned by the decorator does not interpret itself as the calling method. Try removing wraps () from the above code.
sample14.py
>>> def checktime(func):
... def wrapper(*args, **kwargs):
... import time
... start = time.time()
... res = func(*args, **kwargs)
... end = time.time() - start
... print('--------------------------------------------------')
... print(end)
... print('--------------------------------------------------')
... return res
... return wrapper
...
... @checktime
... def wait1():
... time.sleep(1)
... print('owata')
...
... wait1()
... print(wait1)
owata
--------------------------------------------------
1.0004959106445312
--------------------------------------------------
<function checktime.<locals>.wrapper at 0x1118b5ae8> #...?
You can use functools.wraps
to copy the internal function metadata to the external function even if it is wrapped in a decorator.
Python dictionaries are not sorted. However, in a real program, you may want to sort the dictionary keys in the order in which they are inserted. In such a case, collection.OrderedDict
is convenient.
sample15.py
>>> names = ['s', 'p', 'l', 'g']
>>> o = OrderedDict()
>>> for name in names:
... o[name] = 1
>>> o
OrderedDict([('s', 1), ('p', 1), ('l', 1), ('g', 1)])
>>> oo = dict()
>>> for name in names:
... oo[name] = 1
>>> oo
{'p': 1, 'l': 1, 'g': 1, 's': 1}
It returns a pre-determined default value if the key does not exist.
sample16.py
>>> from collections import defaultdict
>>> rec = defaultdict(int)
>>> rec['ore']
0
>>> rec
defaultdict(<class 'int'>, {'ore': 0})
Recently, I enjoy writing documents with Sphinx, but in .git/hooks
sample.sh
#!/bin/sh
#
make html
If you do, I'm happy that the html build will run automatically every time.
I think it's not a lot, but if I read back the Python project I wrote this year, it will come out. It will come out more, and it's been 12th, so I'll put a brush on it. There are many other things, so I'll write it on my blog.
I mentioned it as soon as I came up with it, but I will say goodbye in 2016, thinking that I will reflect on this article later.
Recommended Posts