Python全栈开发之6、面向对象
一、创建类和对象
面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
类是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)
对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
def Dog(name,type):
def call(dog):
print("这是一条%s,名字叫%s"%(dog['type'],dog['name']))
def eat(dog):
print("%s正在啃骨头"%dog['type'])
def init(name,type):
dog_dcit={'name':name,'type':type,'call':call,'eat':eat}
return dog_dcit
res=init(name,type)
return res
d1=Dog('小狗',"中华田园犬")
d1['call'](d1)
d1['eat'](d1)
面向对象设计
类的成员可以分为三大类:字段(类变量)、方法(动态属性)和属性(静态属性)
1、类的语法
在python3.0 中有两种写法,一种是经典类还有一种是新式类
经典类和新式类的区别:继承方法上的区别,分为广度优先和深度优先两种继承策略
class Dog: #经典类,类名后不加括号
def __init__(self,name): #构造函数
self.name=name
def bulk(self):
print('%s,汪汪'%self.name)
d1 = Dog("小红") #初始化一个类 构造一个对象 self相当于d1 Dog(d1,"小红")
d2 = Dog("小明")
d1.bulk()
d2.bulk()
经典类
class Dog(object): #新式类,类名后加括号(object)
def __init__(self,name): #构造函数
self.name=name
def bulk(self):
print('%s,汪汪'%self.name)
d1 = Dog("小红") #初始化一个类 构造一个对象 self相当于d1 Dog(d1,"小红")
d2 = Dog("小明")
d1.bulk()
新式类
2、类变量、方法和属性
类变量:在类中定义的变量class Role(object): #定义类
num=123 #类变量,大家都可以调用
num_list=[]
def __init__(self, name, role, weapon, life_value=100, money=15000): #构造函数 在实例化时做一些类的初始化的工作
self.name = name #self.name 赋给实例 实例变量(静态属性) 作用域就是实例本身
self.role = role
self.weapon = weapon
self.__life_value = life_value #私有属性前面要加两个下划线__来定义,私有属性只可以在方法里面调用
self.money = money
def __del__(self): #析构函数 实例或者对象消亡或者程序结束时才调用
#在实例释放或销毁的时候自动执行,通常用于做一些收尾工作
#如:关闭一些数据库连接,打开的临时文件
print("%s 彻底死了。。。。"%self.name)
def shot(self):
print("shooting...")
def got_shot(self): #定义类的方法(功能)也叫作动态属性
print("ah...,I got shot...")
def buy_gun(self,gun_name):
print("%s just bought %s" %(self.name,gun_name)) #方法里的self self.name 相当于r1.name
def show_life(self):
print("life %s"%self.__life_value) #私有属性 只可以在内部方法里调用
def __get_weapon(self): #定义私有方法 在定义方法名前加两个下划线,私有方法也是只能在类方法中被调用
print('私有方法')
Role_dict=Role.__dict__ # 查看类的属性字典
print(Role_dict)
#输出:{'__module__': '__main__', 'num': 123, 'num_list': [], '__init__': <function Role.__init__ at 0x10ed6c290>, '__del__': <function Role.__del__ at 0x10ed6c320>, 'shot': <function Role.shot at 0x10ed6c710>, 'got_shot': <function Role.got_shot at 0x10ed6c7a0>, 'buy_gun': <function Role.buy_gun at 0x10ed6c830>, '_Role__get_weapon': <function Role.__get_weapon at 0x10ed6c8c0>, 'show_life': <function Role.show_life at 0x10ed6c950>, '__dict__': <attribute '__dict__' of 'Role' objects>, '__weakref__': <attribute '__weakref__' of 'Role' objects>, '__doc__': None}
r1 = Role('Alex', 'police', 'AK47') # 生成一个角色 (初始化一个类,造了一个对象) 把一个类变成一个具体对象的过程叫实列化
# Role(r1,'Alex','police','AK47') r1.name=name 是这样实例的
#Role(r1,'Alex','police','AK47') self.name 相当于 r1.name
# print(r1.__dict__) #查看实例的属性字典
#输出:{'name': 'Alex', 'role': 'police', 'weapon': 'AK47', '_Role__life_value': 100, 'money': 15000}
r2 = Role('Jack', 'terrorist', 'B22') # 生成一个角色
r1.buy_gun('AK-47')
r2.buy_gun('加特林')
r1.n=456
print(r1.n) #输出是456 互不影响
r3=Role('lucy','artist','AK47')
print(r3.n) #输出是123 在实例r1中值被修改 但是在实例r3中不影响,互相独立 只是类在实例化对象时 都独自开辟了一块内存
Role.n=789
print(r1.n,r3.n) #输出 r1.n是456不是789 因为r1.n已经被实例化过r3.n是789
3、类属性的增删查改
class Chinese:
country="China"
def __init__(self,name):
self.name=name
def play_ball(self,ball):
print("%s 正在打 %s"%(self.name))
def sayWord(self,word):
print("%s 说 %s"%(self.name,word))
# 查看类的属性
print(Chinese.country)
# 修改类的属性
Chinese.country ="Japan"
p1=Chinese("allen")
print(Chinese.country,p1.country)
# 删除类的属性
# del Chinese.country
# print(Chinese.country) # 会报错
# 增加类的属性
Chinese.language = "汉语"
p2=Chinese("lucy")
print(Chinese.country,p2.country,p2.language)
print(Chinese.__dict__)
# 函数属性的增删改查
def learning(self,course):
print("%s is learning %s"%(self.name,course))
Chinese.learn=learning
p3=Chinese("Lily")
p3.learn("france")
类属性的增删改查
class Chinese:
country="China"
def __init__(self,name):
self.name=name
def play_ball(self,ball):
print("%s 正在打 %s"%(self.name,ball))
def sayWord(self,word):
print("%s 说 %s"%(self.name,word))
# 查看实例的属性
p1=Chinese("allen")
print(p1.name)
print(p1.play_ball)
# 增加实例的属性
p1.age = 18
print(p1.__dict__)
# 修改实例的属性
p1.age = 19
print(p1.__dict__)
实例属性的增删改查
4、类的组合
class Head:
pass class Foot:
pass class Body:
pass class Person:
def __init__(self,id_num,name): self.id_num=id_num
self.name=name
self.head=Head() # 实例化一个Head类
self.body=Body() # 实例化一个Body类
self.foot=Foot() # 实例化一个Foot类 p=Person("","allen") print(p.__dict__)
组合
class School:
def __init__(self,name,address): self.name=name
self.address=address def academy(self):
print("%s学校的地址是%s"%(self.name,self.address)) class Course:
def __init__(self,course_name,school):
self.course_name=course_name self.school=school s1=School("山东大学","济南")
s2=School("北京大学","北京")
s3=School("深圳大学","深圳") msg="""
1.山东大学
2.北京大学
3.深圳大学
""" while True:
print(msg)
schoolInfo={"":s1,"":s2,"":s3}
choice=input("请选择学校:")
courseName=input("请输入课程名:")
c1=Course(courseName,schoolInfo[choice]) print("课程%s属于%s"%(c1.course_name,c1.school.name))
示例-选课系统
二、面向对象三大特性
面向对象三大特性:封装、继承和多态
1、继承
继承概念的实现方式主要有2类:实现继承、接口继承。
class A(object): #基类
def __init__(self):
print("A") class B(A):
# def __init__(self): # B继承A 单继承
# print("B")
pass class C(A):
# def __init__(self): # C继承A
# print("C")
pass class D(B,C):
#def __init__(self): #D继承B和C 多继承
# print("D")
pass a=D()
继承
子类继承了父类的所有属性。子类自定义的属性如果和父类的属性重名了,那就直接调用自己的属性,不再调用父类的属性。
1.1、继承顺序
Python2中的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
- 当类是经典类时,多继承情况下,会按照深度优先方式查找
- 当类是新式类时,多继承情况下,会按照广度优先方式查找
Python3中统一都是新式类,都是广度优先查找。
class A(object):
def test(self):
print('from A') class B(A):
def test(self):
print('from B') class C(A):
def test(self):
print('from C') class D(B):
# def test(self):
# print('from D')
pass class E(C):
def test(self):
print('from E') class F(D,E):
# def test(self):
# print('from F')
pass
f1=F()
f1.test() # 查找顺序:F --> D --> B --> E --> C --> A
python3新式类广度优先继承
python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表。
例如:
print(F.__mro__) #打印mro列表 [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
1.2、子类中调用父类的方法
class People(object):
def __init__(self, name, age):
self.name = name
self.age = age def eat(self):
print("%s is eating" % self.name) def sleep(self):
print("%s is sleeping" % self.name) def print_tab(self):
print("%s 今年 %s" % (self.name, self.age)) class Relation(object): def make_friend(self, obj):
print("%s is making friends with %s" % (self.name, obj.name)) class Man(Relation, People): # 继承Relation,和People两个基类 def __init__(self, name, age, money):
People.__init__(self, name, age) # 重构经典类写法
# super(Man,self).__init__(name,age) # 新式写法
self.money = money def drink(self):
print("%s is drinking %s" % (self.name, self.money)) def sleep(self): # 基类中也有sleep()方法
People.sleep(self) # 重构基类中sleep()方法后 先调用基类的sleep()方法 再调用自己的方法 如果不重构,就调用自己的sleep()方法
print("man is sleeping") class Women(People, Relation): # 继承Relation,和People两个基类 def get_birth(self):
print("%s is making face" % self.name) m1 = Man("Jim", 20, 100)
m1.drink()
m1.sleep()
m1.eat()
w1 = Women("lucy", 20)
w1.get_birth() m1.make_friend(w1)
# -*-coding:utf-8-*-
class school(object):
def __init__(self,name,addr):
self.name=name
self.addr=addr
self.students=[]
self.teachers=[]
def enroll(self,stu_obj):
print('为%s学员办理注册手续'%stu_obj.name)
self.students.append(stu_obj)
class SchoolMember(object):
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
class Teacher(SchoolMember):
def __init__(self,name,age,sex,salary,course):
super(Teacher,self).__init__(name,age,sex)
self.salary=salary
self.course=course
def tell(self):
print("""-------info of Teacher:---------
name:%s
age:%s
sex:%s
salary:%s
course=%s
""" % (self.name, self.age, self.sex, self.salary, self.course))
def teach(self):
print("%s is teaching course[%s]"%(self.name,self.course))
class Student(SchoolMember):
def __init__(self,name,age,sex,stu_id,grade):
super(Student,self).__init__(name,age,sex)
self.stu_id=stu_id
self.grade=grade
def tell(self):
print("""-------info of student:---------
name:%s
age:%s
sex:%s
stu_id:%s
grade=%s
""" % (self.name, self.age, self.sex, self.stu_id, self.grade))
def pay(self,account):
print("%s paid account:$%d"%(self.name,account))
school1=school('北京大学','北京')
teacher1=Teacher('李老师',30,'男',5000,'Linux')
teacher2=Teacher('陈老师',23,'女',3000,'PHP')
student1=Student('小明',23,'女',1001,'python')
student2=Student('小露',25,'女',1002,'python')
teacher1.tell()
student1.tell()
school1.enroll(student1)
print(school1.students)
school1.students[0].pay(5000)
示例
2、多态
多态指的是一类事物有多种形态,指出了对象如何通过他们共同的属性和动作来操作及访问,而不需要考虑他们具体的类。
一种接口,多种实现 python 不直接支持多态,可以间接实现
class Animal(object):
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")
@staticmethod
def func(obj): # 一个接口,多种形态
obj.talk() class Cat(Animal):
def talk(self):
print('%s: 喵喵喵!' % self.name) class Dog(Animal):
def talk(self):
print('%s: 汪!汪!汪!' % self.name) c1 = Cat('小晴')
d1 = Dog('李磊') Animal.func(c1)
Animal.func(d1)
多态
3、封装
1、封装的特性:双下划线__开头(私有属性和私有方法),类内部可以调用,外部不可调用。
注意: 双下划线开头在外部不能被调用是因为被类重新命名了,其实在外部是可以被调用的。
class Role:
num = 123 # 类变量,大家都可以调用
num_list = []
__info="角色"
def __init__(self, name, role, weapon, life_value=100, money=15000): self.name = name # self.name 赋给实例 实例变量(静态属性) 作用域就是实例本身
self.role = role
self.weapon = weapon
self.__life_value = life_value # 私有属性前面要加两个下划线__来定义,私有属性只可以在方法里面调用
self.money = money def shot(self):
print("shooting...") def got_shot(self):
print("ah...,I got shot...",self.__info) def __get_weapon(self): # 定义私有方法 在定义方法名前加两个下划线,私有方法也是只能在类方法中被调用
print('私有方法',self.__info) r=Role("Jim","武器","ak47")
#print(r.__info) 这样是调用不到的,因为它被类重新命名为_Role__info了
print(Role.__dict__)
#双下划线开头在外部不能被调用是因为被类重命名了
print(r._Role__info) # 私有属性这样就可以调用了
r._Role__get_weapon() # 私有方法这样可以被调用
封装-私有属性和方法
Python全栈开发之6、面向对象的更多相关文章
- 战争热诚的python全栈开发之路
从学习python开始,一直是自己摸索,但是时间不等人啊,所以自己为了节省时间,决定报个班系统学习,下面整理的文章都是自己学习后,认为重要的需要弄懂的知识点,做出链接,一方面是为了自己找的话方便,一方 ...
- python全栈开发之OS模块的总结
OS模块 1. os.name() 获取当前的系统 2.os.getcwd #获取当前的工作目录 import os cwd=os.getcwd() # dir=os.listdi ...
- Python全栈开发之14、Javascript
一.简介 前面我们学习了html和css,但是我们写的网页不能动起来,如果我们需要网页出现各种效果,那么我们就要学习一门新的语言了,那就是JavaScript,JavaScript是世界上最流行的脚本 ...
- Python全栈开发之1、输入输出与流程控制
Python简介 python是吉多·范罗苏姆发明的一种面向对象的脚本语言,可能有些人不知道面向对象和脚本具体是什么意思,但是对于一个初学者来说,现在并不需要明白.大家都知道,当下全栈工程师的概念很火 ...
- Python全栈开发之MySQL(二)------navicate和python操作MySQL
一:Navicate的安装 1.什么是navicate? Navicat是一套快速.可靠并价格相宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设.它的设计符合数据库管理员.开发人员及中小 ...
- Python全栈开发之9、面向对象、元类以及单例
前面一系列博文讲解的都是面向过程的编程,如今是时候来一波面向对象的讲解了 一.简介 面向对象编程是一种编程方式,使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” ...
- Python全栈开发之7、面向对象编程进阶-类属性和方法、异常处理和反射
一.类的属性 1.@property属性 作用就是通过@property把一个方法变成一个静态属性 class Room: def __init__(self,name,length,width,he ...
- python全栈开发之路
一.Python基础 python简介 python数据类型(数字\字符串\列表) python数据类型(元组\字典) python数据类型(集合) python占位符%s,%d,%r,%f prin ...
- Python全栈开发之MySQL(三)视图,存储过程触发器,函数,事务,索引
一:视图 1:什么是视图? 视图是指存储在数据库中的查询的SQL语句,具有简单.安全.逻辑数据独立性的作用及视点集中简化操作定制数据安全性的优点.视图包含一系列带有名称的列和行数据.但是,视图并不在数 ...
随机推荐
- js中showModalDialog的使用
基本介绍: showModalDialog() (IE 4+ 支持) showModelessDialog() (IE 5+ 支持) ...
- closest(expr|object|element)
closest(expr|object|element) 概述 jQuery 1.3新增.从元素本身开始,逐级向上级元素匹配,并返回最先匹配的元素..大理石平台生产厂 closest会首先检查当前元素 ...
- CSS 图片自适应容器
https://www.jb51.net/css/660677.html 经常有这样一个场景,需要让图片自适应容器的大小. 1.img标签的方式 我们马上就能想到,把width.height 设置为1 ...
- 早停!? earlystopping for keras
为了获得性能良好的神经网络,网络定型过程中需要进行许多关于所用设置(超参数)的决策.超参数之一是定型周期(epoch)的数量:亦即应当完整遍历数据集多少次(一次为一个epoch)?如果epoch数量太 ...
- 最近公共祖先lca模板
void dfs(int x,int root){//预处理fa和dep数组 fa[x][0]=root; dep[x]=dep[root]+1; for(int i=1;(1<<i)&l ...
- 锁对象Lock-同步问题更完美的处理方式
Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我 ...
- 4.rabbitmq--路由模式
rabbitmq--路由模式 想象之前的订阅发布模式: 一个生产者,多个消费者,每一个消费者都有自己的一个队列,生产者没有将消息直接发送到队列,而是发送到了交换机,每个队列绑定交换机,生产者发送的消息 ...
- Linux 上的Tomcat配置输入域名直接访问项目
申请的域名备案通过了,域名是在阿里云上面的买的,一块钱,当初买服务器是买着来玩玩的. 既然申请的域名已经备案通过了,也配置了域名解析 ,服务器上也装了Tomcat,部署了web项目,下面来配置下通过域 ...
- 数据结构-用C++实现一个二叉树,递归方法中序遍历
1:二叉排序树,又称二叉树.其定义为:二叉排序树或者空树,或者是满足如下性质的二叉树. (1)若它的左子树非空,则左子树上所有节点的值均小于根节点的值. (2)若它的右子树非空,则右子树上所有节点的值 ...
- CentOS 7服务器下Nginx安装配置
一.安装编译工具及库文件 $ yum -y install make zlib zlib-devel gcc gcc-c++ libtool openssl openssl-devel pcre pc ...