Skip to content

Instantly share code, notes, and snippets.

@domodomodomo
Created June 29, 2018 16:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save domodomodomo/e1f619e7ef7bfbacf66328708a03beed to your computer and use it in GitHub Desktop.
Save domodomodomo/e1f619e7ef7bfbacf66328708a03beed to your computer and use it in GitHub Desktop.
import collections
def sample():
# point 1. 属性はデコレータに文字列で与える。
@immutable(
'x1', 'y1', 'x2', 'y2',
'is_rectangle', 'is_line', 'is_dot')
class Region(object):
# point 2. __init__ ではなく、__new__ を使う。
# オブジェクトが生成される前に呼び出される.
def __new__(cls, x1, y1, x2, y2):
width_0 = (x1 - x2 == 0)
height_0 = (y1 - y2 == 0)
is_rectangle = (not width_0 and not height_0) # 0 0
is_line = (width_0 != height_0) # 0 1 or 1 0; xor
is_dot = (width_0 and height_0) # 1 1
args = (x1, y1, x2, y2, is_rectangle, is_line, is_dot)
# point 3. 必要なオブジェクトが揃ったところで
# オブジェクトを生成する。
self = super(Region, cls).__new__(cls, *args)
# point 4. 生成したオブジェクトを return
return self
"""
# 請注意
# デコレータを使うと省略記法では書けません
self = super().__new__(cls, *args)
"""
def __eq__(self, other):
return all((self.x1 == other.x1,
self.y1 == other.y1,
self.x2 == other.x2,
self.y2 == other.y2))
return Region
def immutable(*attributes):
def decorate(cls):
imm_bases = tuple((collections.namedtuple('ImmBase', attributes), ))
cls_bases = tuple(c for c in cls.__bases__ if c is not object)
bases = imm_bases + cls_bases
ImmutableClass = type(
'Immutable' +
cls.__name__,
bases,
dict(
cls.__dict__))
return ImmutableClass
return decorate
def test(Region):
# 1. 代入はエラーになる。
region = Region(0, 0, 1, 1)
print(region)
try:
region.x1 = 100
except AttributeError as attribute_error:
print(AttributeError, attribute_error)
# 2. def __init__ の代替もできてる。
region1 = Region(0, 0, 1, 1)
print(region1)
print(region1.is_rectangle)
print(region1.is_line)
print(region1.is_dot)
region2 = Region(0, 0, 0, 0)
print(region2)
print(region2.is_rectangle)
print(region2.is_line)
print(region2.is_dot)
# 3. メソッドもちゃんと動作する。
print('region1 == region2 # ', region1 == region2)
if __name__ == '__main__':
test(sample())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment