Python基础部分已经学了一点了。接下来就是进阶部分。
众所周知,Python是面向对象的编程。本篇就来记录Python是如何面向对象的。
我是跟着慕课课程:https://www.imooc.com/learn/1264进行学习的。
第二章 Python面向对象编程
2-2 Python类的定义与实例化
Python中通过class定义一个类。按照编程习惯通常命名类时首字母大写。
class Person: pass上述定义没有继承任何类。还有以下两种定义方式:
class Person(): pass class Person(object): passPython3中,这三种方式是没有区别的。
但是在Python2中,对于第一种定义的方法,Person类只有有限的几个内建函数'__doc__', '__module__', 'name',而对于第二种、第三种定义的方法,则会继承Python object对象的更多的内建函数,可以更便捷的操作对象。
定义完类就可以对它进行实例化了。实例化好比把抽象的类,赋予实物的过程。
创建实例使用 类名+() 类似于函数调用
class Person(object): pass xiaohong = Person() xiaoming = Person()2-3 Python实例属性的定义
前面创建的xiaohong和xiaoming可以通过以下方式赋予属性。
xiaohong.name = 'xiaohong' xiaohong.sex = 'girl' xiaohong.age = 13 print(xiaohong.name) print(xiaohong.sex) print(xiaohong.age)除此之外,这些属性也可以当成普通变量进行运算。
xiaohong.age = xiaohong.age + 1
2-4 Python实例属性的初始化
定义属性时使用了不同的属性名字,如性别分别使用了sex和gender,后期维护就不方便。
抽象一个类时,应当包含基本属性信息。
比如在定义 Person 类时,可以为Person类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用(也就是说我们可以在这个方法里面写一些其它的东西,比如自动计数),我们就能在此为每个实例都统一加上以下属性:
class Person(object): def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age
__init__()方法的第一个参数习惯上都用self,后续参数可以自由指定,和定义函数没有区别。
之后实例化对象时需要提供除self以外的所有参数。
xiaoming = Person('Xiao Ming', 'boy', 13) xiaohong = Person('Xiao Hong', 'girl', 14)访问和使用和之前一样。但是访问不存在的属性会报错。
2-5 Python类属性
如果类上绑定一个属性,所有实例都可以访问类的属性,而且都是同一个。
类属性可以直接在calss中定义。
class Animal(object): localtion = 'Asia' def __init__(self, name, age): self.name = name self.age = age
dog = Animal('wangwang', 1) cat = Animal('mimi', 3) print(dog.localtion) # ==> Asia print(cat.localtion) # ==> Asia # 类属性,也可以通过类名直接访问 print(Animal.localtion) # ==> Asia类属性也可以动态添加和修改。因为类属性只有一份,所以改变了,所有的实例访问都会变更。
2-6 类属性和实例属性的优先级
在类属性和实例属性同名并同时存在的情况下,实例属性的优先级要高于类属性。
比如类属性和实例属性都有location,类属性是Asia,实例属性是Guangdong,这时候实例.location就是Guangdong
不能通过实例修改类属性!!可能会引发各种错误!
这种只是给实例新增了一个实例属性。
2-7 Python中的访问限制
并不是所有属性都可以被外部访问。不能被外部访问的属性称为私有属性。
私有属性以双下划线__开头
# 类私有属性 class Animal(object): __localtion = 'Asia' print(Animal.__localtion) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'Animal' has no attribute '__localtion'
# 实例私有属性 class Animal(object): def __init__(self, name, age, localtion): self.name = name self.age = age self.__localtion = localtion dog = Animal('wangwang', 1, 'GuangDong') print(dog.name) # ==> wangwang print(dog.age) # ==> 1 print(dog.__localtion) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Animal' object has no attribute '__localtion'外部访问私有属性将抛出异常,但是从类的内部是可以访问的。
2-8 定义实例的方法
通过定义实例的方法可以操作私有属性。
class Person(object): def __init__(self, name): self.__name = name def get_name(self): return self.__namename是实例的私有属性,从外部是无法访问的,而get_name(self) 就是一个实例方法,在实例方法里面是可以操作私有属性的,注意,它的第一个参数是self。
实例方法需要在class中定义!!
外部调用实例方法时不需要显示传递self参数。
p = Person('Alice') print(p.get_name()) # ==> Alice使用实例方法来操作私有属性非常方便。实例方法也可以抽象有关类和实例的操作。
2-9 Python定义类方法
类方法也要在class中定义。在类方法前面要写上:
@classmethod
来注明是类方法,否则将被定义为实例方法。
类方法第一个参数,通常命名为cls
class Animal(object): __localtion = 'Asia' def __init__(self, name, age): self.name = name self.age = age @classmethod def set_localtion(cls, localtion): cls.__localtion = localtion @classmethod def get_localtion(cls): return cls.__localtion print(Animal.get_localtion()) # ==> Asia Animal.set_localtion('Afica') print(Animal.get_localtion()) # ==> Africa
3-2 Python继承类
Python GUI时钟
# coding=utf-8 from tkinter import * import _tkinter import math import time from threading import Thread class Clock: def __init__(self, master, x, y, width, height, radius): ''' :param master: 父窗口 :param x: 时钟中心点的x坐标 :param y: 时钟中心点的y坐标 :param width: 画布的宽度 :param height: 画布的高度 :param radius: 时钟钟盘的半径 ''' self.centerX = x self.centerY = y self.radius = radius self.canvas = Canvas(master, width=width, height=height) # 画布 self.canvas.pack() self.canvas.create_line(100,40,300,40,width=3) self.canvas.create_line(300,40,390,213,width=3) self.canvas.create_line(100,40,10,213,width=3) self.canvas.create_line(10,213,100,380,width=3) self.canvas.create_line(100,380,300,380,width=3) self.canvas.create_line(390,213,300,380,width=3) # self.canvas.create_oval(x - radius,y - radius,x + radius,y + radius) # 画钟框 self.id_lists = [] self.hourHandRadius = self.radius * 1.0 / 4 # 指针长度 self.minHandRadius = self.radius * 2.0 / 3 # 分针长度 self.secHandRadius = self.radius * 4.0 / 5 # 秒针长度 self.timeVar = StringVar() # self.timeVar.set('') self.timeLabel = Label(self.canvas.master, textvariable=self.timeVar) self.timeLabel.pack(side=BOTTOM) #self.canvas.master.protocol('WM_DELETE_WINDOW', self.canvas.master.destroy) def __del__(self): self._deleteItems(self.id_lists) # 绘制时钟钟盘 def drawClockDial(self): # 绘制钟盘上的数字1-12 r = self.radius - 15 for i in range(1, 13): rad = 2 * math.pi / 12 * i x = self.centerX + math.sin(rad) * r y = self.centerY - math.cos(rad) * r id = self.canvas.create_text(x, y, text=str(i)) self.id_lists.append(id) # 绘制钟盘上的刻度 r1 = self.radius - 5 r2 = self.radius for i in range(1, 61): rad = 2 * math.pi / 60 * i x1, y1 = self._getPosByRadAndRadius(rad, r1) x2, y2 = self._getPosByRadAndRadius(rad, r2) id = self.canvas.create_line(x1, y1, x2, y2) self.id_lists.append(id) # 显示时间 def showTime(self, tm): hour = tm.tm_hour % 12 min = tm.tm_min sec = tm.tm_sec sec_rad = 2 * math.pi / 60 * sec min_rad = 2 * math.pi / 60 * (min + sec / 60.0) hour_rad = 2 * math.pi / 12 * (hour + min / 60.0) timeStr = '当前时间: %d-%02d-%02d %02d:%02d:%02d' % ( tm.tm_year, tm.tm_mon, tm.tm_mday, hour, min, sec) self.timeVar.set(timeStr) hour_id = self._drawLine(hour_rad, self.hourHandRadius, 6) min_id = self._drawLine(min_rad, self.minHandRadius, 4) sec_id = self._drawLine(sec_rad, self.secHandRadius, 3) return (hour_id, min_id, sec_id) def run(self): def _run(): while True: tm = time.localtime() id_lists = self.showTime(tm) self.canvas.master.update() time.sleep(1) self._deleteItems(id_lists) thrd = Thread(target=_run) # 创建新的线程 thrd.run() # 启动线程 def _drawLine(self, rad, radius, width): x, y = self._getPosByRadAndRadius(rad, radius) fill = 'black' if width==3 else 'green' if width==4 else 'red' id = self.canvas.create_line( self.centerX, self.centerY, x, y, width=width, fill=fill) return id def _getPosByRadAndRadius(self, rad, radius): x = self.centerX + radius * math.sin(rad) y = self.centerY - radius * math.cos(rad) return (x, y) def _deleteItems(self, id_lists): for id in id_lists: try: self.canvas.delete(id) except BaseException: pass if __name__ == '__main__': root = Tk() root.title('赵苦瓜的Python时钟') clock = Clock(root, 200, 200, 400, 400, 150) clock.drawClockDial() clock.run() root.mainloop()
本文地址:https://blog.jixiaob.cn/?post=32
版权声明:若无注明,本文皆为“赵苦瓜のBlog~”原创,转载请保留文章出处。