class Point(object):
'''a 2D point with attr: x, y'''
def __init__(self, x , y):
self.x = x
self.y = y
def __str__(self):
return 'Point[ x = {0}, y = {1} ]'.format(self.x, self.y)
class Rectangle(object):
'''Rectangle, represented by it left lower corner, width and height'''
def __init__(self, point, width, height):
self.corner = point
self.width = width
self.height = height
def __str__(self):
return 'Rectangle[ corner = {0}, width = {1}, height = {2} ]'.format(self.corner, self.width, self.height)
# 创建一个对象, 只需要通过 类名()的方式, 括号中需要传入__init__函数中指定的参数
p1 = Point(20, 30)
p2 = Point(20, 30)
print(p1 is p2) # p1 和 p2不是同一个对象
print(p1 == p2) ## 自定义的类, 使用==号运算时, 其行为默认与 is 类似, 就是判断两个变量是否引用了同一个对象
import copy
box1 = Rectangle(p1, 100, 200)
box2 = copy.copy(box1)
print('box1 : ', box1)
print('box2 : ', box2)
# copy 函数复制并创建了一个新的对象, 两个对象有相同的值和引用, 是浅拷贝
print('box1 is box2 : ', box1 is box2)
print('box1 == box2 : ', box1 == box2 )
# box1.corner 和box2.corner引用了同一个对象, 因此 is 和 == 都返回 True
print('box1.corner is box2.corner : ', box1.corner is box2.corner)
print('box1.corner == box2.corner : ', box1.corner == box2.corner)
box3 = copy.deepcopy(box1)
# 由于box3是通过深拷贝创建的, box3中的变量和引用(以及引用的引用)都是原对象的副本,
# 而不再引用同一个对象, 是深拷贝
print('box1 : ', box1)
print('box3 : ', box3)
print('box1.corner is box3.corner : ', box1.corner is box3.corner)
print('box1.corner == box3.corner : ', box1.corner == box3.corner)
class Time():
'''
represent the time of a day
attr : hour, minute, second
'''
def __init__(self, hour=0, minute=0, second=0):
self.hour = hour
self.minute = minute
self.second = second
def __str__(self):
return '%.2d : %.2d : %.2d'%(self.hour, self.minute, self.second)
# 下面两个是类的方法, 调用的时候需要 用 类名.method() 的形式
def timeToInt(time):
return time.hour * 3600 + time.minute * 60 + time.second
def intToTime(second):
time = Time()
minute ,time.second = divmod(second, 60)
time.hour, time.minute = divmod(minute, 60)
return time
# 重载小于号 < 运算符
def __lt__(self, other):
return Time.timeToInt(self) < Time.timeToInt(other)
# 重载等于号 ==
def __eq__(self, other):
return Time.timeToInt(self) == Time.timeToInt(other)
# 重载 + 运算符
# self + other 时调用该函数
def __add__(self, other):
''' other can be a integer or another time '''
if isinstance(other, Time):
second = Time.timeToInt(self) + Time.timeToInt(other)
return Time.intToTime(second)
else: # assume other is a integer
second = Time.timeToInt(self) + other
return Time.intToTime(second)
# other + self 时调用该函数
def __radd__(self, other):
return self + other
#使用关键字参数, 增加指定的时间单位
def increase(self, *, hour=0, minute=0, second=1):
second = hour * 3600 + minute * 60 + second + Time.timeToInt(self)
minute, self.second = divmod(second, 60)
self.hour, self.minute = divmod(minute, 60)
# test Time
t1 = Time(6,6,6)
t2 = Time(11, 11, 11)
t3 = t1 + t2
print('t1 = ', t1)
print('t2 = ', t2)
print('t3 = t1 + t2 , t3 = ', t1 + t2)
t4 = copy.copy(t3)
t4.increase(minute=100, second=80)
print('t4 = ', t4)
print('t4 + 100 = ', t4 + 100)
# 如果没有定义 __radd__(), 这里将会报错, 因为编译器不知道如何将一个时间加到一个整数上
print('300 + t4 = ', 300 + t4)
# 由于Time定义了 < 号 运算, 因此可以对其进行排序
t = [t1, t2, t3, t4, Time() ]
# 要想同时获得元素的下标和对应的元素, 可以使用 enumerate()来封装要遍历的集合
for idx, tm in enumerate(sorted(t)) : print(idx , ' ', tm)
# 测试等于号
# t5 = copy.deepcopy(t[1])
t5 = Time(6,6,6)
print('t1 = ', t1)
print('t5 = ', t5)
print('t1 == t5:', t1 == t5)
print('t[0] == t[1] : ', t[0] == t[1] )
# 先了解两个 built-in 函数, 使用这两个函数可以对一个陌生的类或对象进行分析
# vars(obj) 返回一个字典, 该字典以键值对的形式包含了obj对象所定义的类中所有的public属性和其对应的值
print(vars(t4))
# dir(obj) 返回一个字符串列表,列出了该对象所有的属性和函数,包括以__开头和结尾的
print(dir(t4))
# 当我们不知道一个对象是否有某个属性或者方法时, 使用 hasattr()会避免报错
print('t4 = ', t4)
if hasattr(t4, 'minute'):
print(getattr(t4, 'minute'))
if hasattr(t4, 'hour'):
setattr(t4, 'hour', 10)
print('t4 = ', t4)
if hasattr(t4, '__add__'): # 如果定义了 __add__()函数, 则可以使用 + 运算符
print('t4 + t4 = ', t4 + t4)
# 恰当使用 hasattr() 的例子
def readFile(reader):
file = 'config.xml'
if hasattr(reader, 'read'):
return reader.read(file) # 当不确定reader是否有'read'方法的时候, 这样写可以避免出错
class Student():
def __init__(self, name, score, age):
self.name = name
self._score = score
self.__age = age
self.__other__ = 'other'
def get_age(self):
return self.__age
s = Student('juliya', 90, 20)
print(s.name)
print(s._score)
print(s.__other__)
print(s.get_age())
try:
print(s.__age) # 访问私有属性, 这里将报错
except Exception as e:
print(e)
class Student():
name = 'student'
__name__ = 'student'
__name = 'student'
def __init__(self):
pass
s = Student()
print('Student.name = ', Student.name)
print('s.name = ',s.name)
print('s.__name__ = ', s.__name__)
try:
print('s.__name = ',s.__name)
except Exception as e:
print(e)
s.name = 'jack' # 给实例对象绑定同名属性, 将覆盖同名的类属性
print('s.name = ',s.name)
if hasattr(s, 'name') :
del s.name # 删除实例对象的属性
if hasattr(s, 'name'):
print('s.name = ', s.name) # 将输出类的 name 属性的值 'student'
if hasattr(Student, 'name') :
del Student.name # 删除类的属性
if hasattr(s, 'name') : # False
print(s.name)