Created
June 29, 2018 16:31
-
-
Save domodomodomo/e1f619e7ef7bfbacf66328708a03beed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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