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 ...
随机推荐
- IOS 表视图(UITableVIew)的使用方法(7)表视图的编辑功能(拖拉调整排序位置)
除了每个单元行左边的删除和新增图标,UITableView还支持在单元行的右侧显示一个供用户拖拉调整排序位置的控件. 不过如果要显示此控件,UITableView的数据源需要实现以下的方法. -(vo ...
- BeanUtils复制属性
package xiao; public class User2 { private String name; private String password; public String getNa ...
- 我的Fedora环境
Fedora现在也更新到了第20个版本,只是在15+以后的版本,大多数操作,都是大同小异的,也不必特意去关注版本号,只有对应到具体的软件,可能会因为库的版本,有或多或少的区别. 之前每次都喜欢按照一些 ...
- S70卡
产品名称:Mifare 4K(S70)卡 芯片类型:Philips Mifare 1 S70(MOA2) 存储容量:32Kbit,32个分区,每分区两组密码 工作频率:13.56 MHz 通讯 ...
- qt数据库多线程问题的解决(QSqlDatabase只能在创建它的线程中使用)
Qt数据库由QSqlDatabase::addDatabase()生成的QSqlDatabase只能在创建它的线程中使用, 在多线程中共用连接或者在另外一个线程中创建query都是不支持的几乎国内没有 ...
- Hibernate JPA中@Transient、@JsonIgnoreProperties、@JsonIgnore、@JsonFormat、@JsonSerialize等注解解释
@jsonignore的作用作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响. http://www.cnblogs.com/toSeeMyDream/p/443 ...
- Windows Azure 成为业内首家被授权为 FedRAMP JAB P-ATO 的供应商
编辑人员注释:本文章由 Windows Azure 业务和运营部门产品市场营销总监 Sarah Fender 撰写 我们高兴地宣布,Windows Azure 被 FedRAMP 联合授权董事会 (J ...
- JSTL与EL(转)
基本使用 <c:forEach items="${deptList}" var="dept"> <div ...
- 如何设计一个 iOS 控件?(iOS 控件完全解析)
前言 一个控件从外在特征来说,主要是封装这几点: 交互方式 显示样式 数据使用 对外在特征的封装,能让我们在多种环境下达到 PM 对产品的要求,并且提到代码复用率,使维护工作保持在一个相对较小的范围内 ...
- fopen()函数
1.2 文件的输入输出函数 键盘.显示器.打印机.磁盘驱动器等逻辑设备, 其输入输出都能够通过文件管理的方法来完毕.而在编程时使用最多的要算是磁盘文件, 因此本节主要以磁盘文件为主, 具体介绍Turb ...