Python之路Day7
第7天主要是面向对象的内容。
学到现在越来越吃力了,从上节课开始博客就没时间写了,看看别人写的博客都那么棒。又想起了那句话比你牛逼的人都在努力,你却在放羊。。。唉,我写作业的效率有点低,以后得抓紧时间了。
摘要:
1. 面向对象的编程方法
2. 面向对象的三大特性
3. Python类相关知识
4. 反射(经常用到)
1. 面向对象的编程方法
1.1 什么是面向对象的编程方法?
面向对象编程(Object-Oriented Programming ):将所需要设计的对象抽象成各类具体的属性,它的集合就是类。开发正规的程序跟写一个运行一次就扔了的小脚本一个很大不同就是,你的代码总是需要不断的更改,不是修改bug就是添加新功能等,所以为了日后方便程序的修改及扩展,你写的代码一定要遵循易读、易改的原则(专业数据叫可读性好、易扩展)。其实OOP编程的主要作用也是使你的代码修改和扩展变的更容易。
1.2 为什么要面向对象编程?
是为了更好地处理:1)避免写重复代码,2)灵活的修改代码
1.3 面向对象编程与函数式编程的区别?
面向对象编程=>创建对象,通过对象执行方法
函数式编程=>执行函数
2. 面向对象的三大特性
面向对象的三大特性:封装、继承、多态
2.1 封装
封装可以分为两部分来理解:1)封装,2)调用封装
# 创建一个Person类
class Person(object):
# 类的构造方法,实例化时自动执行
def __init__(self, name, age):
self.name = name
self.age = age
# 实例化一个Person类的对象,自动执行类中的__init__方法
# 将alex和18封装到person1的name和age属性中
person1 = Person("alex", 18)
# 实例化一个Person类的对象,自动执行类中的__init__方法
# 将qimi和20封装到person2的name和age属性中
person2 = Person("qimi", 20)
# 调用alex的封装
print(person1.name) # 输出=> alex
# 调用20的封装
print(person2.age) # 输出=> 20
2.2 继承
对于面向对象来说,继承其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
# 创建一个Person类
class Person(object):
# 父类的构造方法,实例化时自动执行
def __init__(self, name, age):
self.name = name
self.age = age
# 父类的方法
def print(self):
print("{} is {} years old.".format(self.name, self.age))
# 定义一个Teacher的类,继承Person类
class Teacher(Person):
# 不推荐这么写
# def __init__(self, habit):
# super(Person, self).__init__()
# self.habit = habit
# 旧的写法,也不推荐这么写
# def __init__(self, name, age, habit):
# Person.__init__(self, name, age)
# self.habit = habit
# 推荐写法,在子类的构造方法里只出现子类的类名
def __init__(self, name, age, habit):
super(Teacher, self).__init__(name, age)
self.habit = habit
# 或者可以写得更简单一些,跟上面的写法是等价的。 def __init__(self, name, age, habit):
super().__init__(name, age)
self.habit = habit
# 定义一个方法
def get_habit(self):
print("The habit of {} is {}.".format(self.name, self.habit))
# 实例化一个老师
alex = Teacher("alex", 18, "Girl")
# 调用父类的方法
alex.print()
# 调用本类的方法
alex.get_habit()
==============================================
output==>
alex is 18 years old.
The habit of alex is Girl.
多继承:
class D(object):
def bar(self):
print 'D.bar'
class C(D):
def bar(self):
print 'C.bar'
class B(D):
def bar(self):
print 'B.bar'
class A(B, C):
def bar(self):
print 'A.bar'
a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
经典类(深度优先):首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中没有,则继续去C类中找,如果还是未找到,则报错。
新式类(广度优先):首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中没有,则继续去D类中找,如果还是未找到,则报错。
注意:①在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了。
②Python3里为广度优先。
2.3 多态
# 定义父类Animal
class Animal:
def __init__(self, name): # Constructor of the class
self.name = name
# 定义一个供子类复写的方法
def talk(self): # Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
# 定义子类Cat
class Cat(Animal):
def talk(self):
return 'Meow!'
# 定义子类Dog
class Dog(Animal):
def talk(self):
return 'Woof! Woof!'
# 实例化一个Cat、一个Dog
animals = [Cat('Missy'), Dog('Lassie')]
for animal in animals:
print("{} : {}".format(animal.name, animal.talk()))
用Python实现多态
3. Python类的相关知识

3.1 字段(变量)
① 普通字段属于对象、静态字段属于类。
② 普通字段需要通过对象来访问、静态字段通过类访问。
③ 静态字段在内存中只保存一份、普通字段在每个对象中都要保存一份。
因此:通过类创建对象时,如果每个对象都具有相同的字段,那么就应该使用静态字段。
3.2 方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
① 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self。
② 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls。
③ 静态方法:由类调用;无默认参数。
class Animal(object):
def __init__(self, name):
self.name = name
self.num = None
def say_hi(self): # 普通方法,由实例调用访问实例变量
print("Hi~ {}".format(self.name))
@classmethod # 类方法,不能访问实例变量
def talk(cls):
print(" is talking.")
@staticmethod # 静态方法,不能访问类变量及实例变量
def walk():
print("{} is walking.")
相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。
3.3 属性
class Animal(object):
def __init__(self, name):
self.name = name
self.num = None
@property # 把方法变成属性,可以调用实例变量
def habit(self):
return "{}'s habit is eating.".format(self.name)
@property # 定义类属性
def total_animals(self):
return self.num
@total_animals.setter # 给类属性赋值
def total_animals(self, num):
self.num = num
print("total animals: {}".format(self.num))
@total_animals.deleter # 删除类属性
def total_animals(self):
del self.num
print("total animals is deleted.")
# 访问habit属性
a = Animal("tommie")
# 访问类属性,调用时不需要加括号
print(a.habit)
a.say_hi()
# 打印类属性
print(a.total_animals)
# 给类属性赋值
a.total_animals = 10
print(a.total_animals)
# 删除类属性
del a.total_animals
try:
print(a.total_animals)
except AttributeError as e:
print(e)
==============================================
output:
tommie's habit is eating.
Hi~ tommie
None
total animals: 10
10
total animals is deleted.
'Animal' object has no attribute 'num'
实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:
① 根据用户请求的当前页和总数据条数计算出 m 和 n。
② 根据 m 和 n 去数据库中请求数据。
# ############### 定义 ###############
class Pager:
def __init__(self, current_page):
# 用户当前请求的页码(第3页、第7页...)
self.current_page = current_page
# 每页默认显示10条数据
self.per_items = 10
@property
def start(self):
val = (self.current_page - 1) * self.per_items
return val
@property
def end(self):
val = self.current_page * self.per_items
return val
# ############### 调用 ###############
p = Pager(1)
p.start 就是起始值,即:m
p.end 就是结束值,即:n
example code
"""
静态字段方式设置类属性
"""
class Foo(object):
def bar(self):
return "john"
# *必须两个参数
def set_bar(self, value):
print("set value:{}".format(value))
def del_bar(self):
print("delete value")
BAR = property(bar, set_bar, del_bar, "description")
obj = Foo()
print(obj.BAR) # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
del Foo.BAR # 自动调用第三个参数中定义的方法:del_bar方法
print(obj.BAR.__doc__) # 自动获取第四个参数中设置的值:description...
静态字段方式设置类属性
4. 反射
"""
贯穿开发周期内都会用到的:hasattr,setattr,getattr,delattr的介绍
传说中的反射,通过名字的字符串获取相应对象的内存地址
"""
import sys
class WebServer(object):
def __init__(self, host, post):
self.host = host
self.post = post
def start(self):
print("Server is starting...")
def stop(self):
print("Server is stopping...")
def restart(self):
self.stop()
self.start()
# 定义一个类外面的方法
def test_run(res):
print("{} {} is running...".format(res.host, res.post))
if __name__ == "__main__":
server = WebServer("localhost", 33)
# 判断实例中是否有命令行参数同名的方法名
if hasattr(server, sys.argv[1]):
func = getattr(server, sys.argv[1]) # 获取对应类方法的内存地址
# 执行上面获取的方法,可带参数。
func()
# setattr # 把一个类外面的方法绑定到一个类对象中
setattr(server, "run", test_run)
server.run(server)
# delattr # 删除类方法
delattr(WebServer, "stop")
print("=======" * 10)
server.restart()
5.类的特殊成员
"""
类的特殊成员
"""
class A(object):
"""
这是一个测试的类。。。
"""
pass
# __doc__ 表示类的描述信息
print(A.__doc__)
# __module__ 表示当前操作的对象在那个模块
a = A()
print(A.__module__) # __main__
print(a.__module__) # __main__
# __class__ 表示当前操作的对象的类是什么
print(a.__class__) # <class '__main__.A'>
# __init__ 构造方法,通过类创建对象时,自动触发执行
# __del__ 析构方法,当对象在内存中被释放时,自动触发执行。?用于关闭构造方法中打开的文件或数据库?
# __call__ 实例对象后面加括号直接执行
# 构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
Python之路Day7的更多相关文章
- Python之路,Day7 - Python基础7 面向对象
本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...
- python之路-Day7
编程范式 编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方 ...
- Python之路
Python学习之路 第一天 Python之路,Day1 - Python基础1介绍.基本语法.流程控制 第一天作业第二天 Python之路,Day2 - Pytho ...
- Python之路,Day7 - 面向对象编程进阶
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 经典类vs新式类 把下面代 ...
- python学习之路-day7
本节内容: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 面向对象高级语法部分 静态方法 ...
- Python之路【第一篇】python基础
一.python开发 1.开发: 1)高级语言:python .Java .PHP. C# Go ruby c++ ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...
- Python之路第一课Day7--随堂笔记(面向对象编程进阶...未完待续 )
本节内容: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 一.静态方法 通过@s ...
- python之路七
静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量 ...
- python之路 目录
目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...
随机推荐
- 高性能javascript 学习笔记(1)
加载和运行 管理浏览器中的javascript代码是个棘手的问题,因为代码运行阻塞了其他浏览器处理过程,诸如用户绘制,每次遇到<script>标签,页面必须停下来等待代码下载(如果是外部的 ...
- ios 学习笔记(8) 控件 按钮(UIButton)的使用方法
在实际开发中,对于开发者来说,更多的还是使用“自定义”按钮.将“按钮”对象的类型设置成UIButtonTypeCustom.这样一来,按钮的所有元素都将由开发者来配置和自定义. 对于一个自定义按钮来说 ...
- Delphi调试DLL 不能调试 不能进入调试 注意!!!
如何调试DLL,在这里就不再赘述了,但是,今天就碰到了一个特别奇怪的问题,参数设置正确,就是不能调试?? 通过上网查资料,发现了问题,注意: 1, 将Project主菜单的Project Option ...
- PHP glob() 函数用法
glob() 函数返回匹配指定模式的文件名或目录. 该函数返回一个包含有匹配文件 / 目录的数组.如果出错返回 false. 语法 array glob ( string $pattern [, in ...
- mfc添加气球式提示栏
// TOOLTIPWND.H 添加气球式提示栏 #if !defined(AFX_TOOLTIPWND_H__2C52D3E4_2F5B_11D2_8FC9_000000000000__IN ...
- VCS引起的oracle数据库异常重新启动一例
1. 环境描写叙述 操作系统版本号:SUSE Linux Enterprise Server 10 sp2 (x86_64) 数据库版本号:Oracle 11.1.0.7.16 VCS版本号:5.1 ...
- c 输入两个数,第一个数决定一个nXn的矩阵,第二个数决定从1开始赋值,赋值的上限 (MD花了半天时间,思路不对害死人)
输入两个数,第一个数决定一个nXn的矩阵,第二个数决定从1开始赋值,赋值的上限 比如: 输入: 输出: 输入: 输出: #include<stdio.h> int main(void) { ...
- windows 2008 远程端口3389修改小记
修改远程端口使服务器更加安全,win2008上大致与win2003的配置差不多,有些细微的差别,在此小记一下. 简要步骤: 1.打开远程连接功能(默认都是已经打开的) :开始>计算机>属性 ...
- javaweb学习路之二--上传gitgub
代码上传github 代码上传到github的步骤 第一步:申请github账号 https://github.com/注册账号 第二步:登录github,新建repository仓库,命名,创建 第 ...
- JPEG概述和头分析(C源码)
原创文章,转载请注明:JPEG概述和头分析(C源码) By Lucio.Yang 部分内容来自:w285868925,JPEG压缩标准 1.JPEG概述 JPEG是一个压缩标准,又可分为标准 JPE ...