class Point: '''This is a doc string''' # 不需要 new 關鍵字 p = Point() print(p) # <__main__.Point object at 0x01C5BD70> print(p.__doc__) # This is a doc string # 動態建立欄位 p.x = 3 p.y = 4 print('(%d, %d)' % (p.x, p.y)) # (3, 4) import math print(math.sqrt(p.x**2 + p.y**2)) # 5.0
__init__() 與 __str__()
當然也可以預先定義屬性(API),這裡的__init__() 就是 Java 的 constructor,並定義 __str__() 回傳的字串,也就是 Java 裡的 toString()。class Point: '''This is a doc string''' def __init__(self, x=0, y=0): # 可以給預設值,也可以不要 self.x = x self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) p = Point() # 使用預設值 print(p) # Point (0, 0) p.x = 3 p.y = 4 print(p) # Point (3, 4) print(Point(1, 2)) # Point (1, 2) 使用自訂值
物件特徵
和 Java 一樣,Python 物也是 pass by reference 與 mutable。class Point: '''This is a doc string''' def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) p = Point() # print(p.z) # 存取未定義的屬性會得到 AttributeError print(hasattr(p, 'x')) # True print(hasattr(p, 'z')) # False # try-except try: z = p.z except AttributeError: z = 0 print(z) # 0 # 型別檢查 print(type(p)) # <class '__main__.Point'> print(isinstance(p, Point)) # True
克隆
class Point: '''This is a doc string''' def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) p = Point() p2 = p print(p is p2) # True print(p == p2) # True p.x = 5 print(p2) # Point (5, 0) import copy p3 = copy.copy(p) # 淺層複製 print(p is p3) # False,已經是不同物件(reference) print(p == p3) # False,理論上應該是 True,但自訂物件預設的 == 是 is p3.y = 10 print(p) # Point (5, 0) print(p2) # Point (5, 0) print(p3) # Point (5, 10) p4 = copy.deepcopy(p) # 深層克隆
__eq__() 與 ==
透過自訂 __eq__() 來實做 == 的行為。class Point: '''This is a doc string''' def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) def __eq__(self, other): return (self.x, self.y) == (other.x, other.y) p = Point() import copy p3 = copy.copy(p) print(p is p3) # False print(p == p3) # True,透過自訂 __eq__() 來實做 == 的行為,取代預設的 is
Class and instance attributes
class Point: '''This is a doc string''' original = 0 # class attribute def __init__(self, x=0, y=0): self.x = x # instance attributes self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) p = Point(3, 4) print(p) # Point (3, 4) print(Point.original)
Static and instance method
在 Python,method 可以同時是 static 與 instance。class Point: '''This is a doc string''' def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) def print(self): return self.__str__() p = Point(3, 4) print(Point.print(p)) # Point (3, 4) static 呼叫 print(p.print()) # Point (3, 4) instance 呼叫
運算子重載 Operator overloading
只要 class 定義了 __add__(),就可以對 object 使用 +。class Point: '''This is a doc string''' def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) def __add__(self, other): return Point(self.x + other.x, self.y + other.y) p1 = Point(3, 4) p2 = Point(2, 1) print(p1) # Point (3, 4) print(p2) # Point (2, 1) print(p1 + p2) # Point (5, 5)還有其他運算子重載可以定義(__sub__、__mul__、__mod__等),當然前提是情境必須「合適」。
上面的重載是算術運算子,也可以重載比較運算子,前提也是情境必須「合適」。
甚至可以針對不同型別進行運算。
class Point: '''This is a doc string''' def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return 'Point (%d, %d)' % (self.x, self.y) def __add__(self, other): if isinstance(other, Point): return Point(self.x + other.x, self.y + other.y) else: return Point(self.x + other, self.y) def __radd__(self, other): return Point(self.x, self.y + other) p1 = Point(3, 4) p2 = Point(2, 1) print(p1) # Point (3, 4) print(p2) # Point (2, 1) print(p1 + p2) # Point (5, 5) 呼叫 __add__ print(p1 + 3) # Point (6, 4) 呼叫 __add__ print(5 + p1) # Point (3, 9) 呼叫 __radd__甚至只要 class 定義了 __add__(),也就是支援 +,其他使用 + 的函式都可以用了,例如 sum()。
print(sum([Point(1, 2), Point(2, 3), Point(3, 4)])) # Point (6, 9)
繼承
目前只知道 method 有繼承下來,但 attribute 沒有,也不知道可不可以存取 super class 的 attribute。class Point3D(Point): def __init__(self, x=0, y=0, z=0): self.x = x self.y = y self.z = z p2 = Point3D(3, 4, 5) print(p2) # Point (3, 4)
Debug or Reflection
可以使用 vars()、getattr() 與 setattr() 檢視或操作物件屬性。p = Point(3, 4) print(vars(p)) #{'x': 3, 'y': 4} dict of attributes and values print(getattr(p, 'x')) # 3 setattr(p, 'x', 5) print(getattr(p, 'x')) # 5---
---
---
沒有留言:
張貼留言