
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.__name
name是实例的私有属性,从外部是无法访问的,而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~”原创,转载请保留文章出处。









