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 ...
随机推荐
- jqmobile
标准页面结构 <!DOCTYPE html> <html> <head> <title>Page Title</title> <lin ...
- hdu 4119 Isabella's Message
Isabella's Message Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- elk 分布式数据同步
zjtest7-redis:/elk/elasticsearch/data/es_cluster/nodes/0/indices/library# strings ./1/index/_3.cfs | ...
- Baby Step Gaint Step
给定同余式,求它在内的所有解,其中总是素数. 分析:解本同余式的步骤如下 (1)求模的一个原根 (2)利用Baby Step Giant Step求出一个,使得,因为为素数,所以有唯一解. (3)设, ...
- mySQL中replace的用法
MySQL replace函数我们经常用到,下面就为您详细介绍MySQL replace函数的用法,希望对您学习MySQL replace函数方面能有所启迪 mysql replace实例说明: ...
- [置顶] Asp.Net底层原理(一、浏览器和服务器的交互原理)
…… 一.浏览器和服务器的交互原理 二.写自己的"迷你"Asp.net框架 三.Asp.Net的请求与响应过程 1.在此之前,首先简单的模拟一下我们去请求一个网址的时候,浏览器和服 ...
- Android调用系统关机与重启功能
我是在android源码里编译的package/apps/,因为需要调用的关机接口是不对上层开放的,在eclipse里面不能调用. 我主要是介绍调用android的关机功能,因为在调试过程中,关机的一 ...
- python下异常处理
1.python下异常如何处理: #encoding=utf-8 """ python遇到异常,程序直接运行 try: "判断有可能抛出异常的代码" ...
- js中函数参数基本类型和引用类型的区别
高级程序设计中说明,所有函数的参数都是按值传递的. 基本类型 向参数传递基本类型的值时,被传递的值会被复制给对应的命名参数 function addTen(num){ num=+10; return ...
- jquery 动态增加的html元素,初始化设置在id或class上的事件无效
一般情况,我们会在页面初始化完成后对class定义一些全局事件,举个栗子: $(document).ready(function(){ $(".class").on("m ...