文章目录
博客cpen_web
练习1 用代码定义一个人
#注:OOP - 面向对象编程
#注:shell不支持面向对象的编程
用代码定义一个人,有以下信息:
姓名、年龄、性别
上网(年龄大于6岁可以上网,并返回网站内容)
示例
import requests
#注:requests模块抓取网页内容
def person_info(name, age, sex):
return {"name":name,"age":age,"sex":sex}
def brower(user,url):
if user["age"] < 18:
return "不能上网,未到法定年龄"
else:
return requests.get(url).text # 注:返回网页内容
wy = person_info("wy",18,"fmale")
print(brower(wy,"http://www.baidu.com"))
#结果为 <!DOCTYPE html> # 注:返回网页内容
#<!--STATUS OK--><html> ……
wy = person_info("wy",16,"fmale")
print(brower(wy,"http://www.baidu.com"))
#结果为 不能上网,未到法定年龄
知识点2 什么是面向对象
#注:函数封装,实现复用
#注:面向对象 把 变量和函数 再做1层封装
·面向对象编程 (OOP-Object Oriented Programming)
·把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。
#注:在变量和函数外面又封装1层
#注:重点
·类的基本特点:封装、继承和多态
·封装(Encapsulation)
·在类中对数据的赋值、内部调用对外部用户是透明的。
·把一些功能的实现细节不对外暴露
·继承(Inheritance)
·继承:即一个派生类(derived class)继承基类(base class)的字段和方法。
·为实现代码的重用, 一个类可以派生出子类
·继承也允许把一个派生类的对象作为一个基类对象对待。
·多态(Polymorphism) # 注:Python里面多态不是很明显
·接口重用
·一个接口,多种实现(重写)
#面向对象
#把编程当做造物主的这种思想
#车[有轮子,可以载人,可以跑](类) --> (自行车-->有链子,2个轮子,或者3个轮子)(类)
#自行车属于车的子类,可以继承车的属性
#车牌号为 湘A595959 为 对象(实实在在的)
#类(模板,具有某种属性) 对象(通过模板制造出来的)
#Python里一切皆对象
示例
>>> a = "123" # 注:a是 str类的对象
>>> type(a) # 注:str类
<class 'str'> # 注:类 定义好了 属性和方法,对象具有类的所有属性和方法
知识点3 类的定义和使用
·类的定义
·类名的规范
·一般首字母大写(大驼峰)
·Person, GoodsInfo
·函数的命名
·由小写字母和下划线组成
·scan_book, drink
·类的定义方式(关键字:class)
·python2 => 经典类和新式类
·python3 => 新式类
·定义最简单的类
示例:类的定义
#类的定义
class A():
pass
class B:
pass
class C(object):
pass
#注:object是新式类中所有类的 父类
#Python2、3的差异
#python3中3种定义方式,都没有区别,默认就会继承object类
# python2显示定义了object类,才会继承object
#python2 --> 经典类,新式类
#python3 --> 新式类
#继承object类 属于新式类,没有继承object类 属于经典类
#在python2种 A、B 两类都属于经典类,只有C是新式类
#在python3中 默认会继承object类,所有A、B、C都是新式类
练习4 定义一个类
定义一个类
·类名:Bus317
·属性:prod (车品牌)
·方法:run (运行线路), 注意self
使用Bus317类
·实例化
·获取实例属性、调用方法
示例
class Bus317(object):
#类属性
line = "317" #注:描述信息,属性 是317号线路
#方法 --> 行为 (不叫函数了)
def run(self, flag): #注:flag确定从哪边到哪边
print("Bus317 run") #注:类的方法,定义动作、行为
if flag == 0:
print("从农大到长华小区")
else:
print("从长华小区到农大")
print(id(Bus317)) # 注:类创建后可以找到它,存放在类空间
#结果为 2105953133088
#实例化对象
bus01 = Bus317()
#Bus317 --> 类对象
#bus01 --> 实例对象
#获取属性和实例方法 (通过对象)
print(dir(bus01)) # 注:查看属性和方法
#结果为 ['__class__',…… 'line', 'run']
print(bus01.line) # 注:几号线
#结果为 317
#注:用 . 获取 属性和方法
#通过类的对象 获取属性
bus01.run(0) # 注:方法需要用()来获取类的方法
#结果为 从农大到长华小区
#self代表这个实例,不用传,传第2个参就行了 run(self, flag)
#也可以直接 通过类 获取属性
print(Bus317.line) # 注:通过类获取类属性
#结果为 317
#注:也可以实例化多个对象,每个对象都是独立的,公有的是类的一切属性和方法
知识点5 init new
示例1:__init__方法
######__init__方法 实例对象的构造方法(初始化方法)
class Bus317:
#类属性
line = "317"
prod = "BYD"
tmp_class_lst = []
#实例属性
def __init__(self, car_num, name): # 注:定义初始化方法
#注:想传值接参数,不想传值就写死了
#实例属性
self.car_num = car_num
self.name = name
self.line = "318"
self.color = "红色"
self.tmp_object_lst = []
#方法 --> 行为
def run(self, flag):
if flag == 0:
print("从农大到长华小区")
else:
print("从长华小区到农大")
######获取实例属性
bus01 = Bus317("湘A3333", "zhanghuayou")
bus01.prod="五菱宏光"
#有参数需要传它的初始化参数
print(bus01.name)
#结果为 zhanghuayou
print(bus01.prod)
#结果为 五菱宏光
print(bus01.line) # 注:实例化对象使用的是实例的
#结果为 318 # 注:实例化对象使用的是实例的
bus02 = Bus317("湘A4444","fengcheng")
print(bus02.prod)
#结果为 BYD
print(bus02.name)
#结果为 fengcheng
print(bus02.line)
#结果为 318
#通过类获取属性
print(Bus317.line)
#结果为 317
# print(Bus317.color) # 注:报错 AttributeError
#不能通过类获取实例属性
# Bus317.run() # 注:报错TypeError 缺少 'self' and 'flag'
#有self都是属于实例的,只有实例化对象才能访问 使用
######实例空间和类空间
#创建实例的时候会去执行__init__
#实例化对象 --> 生成1个实例空间 --> 不同的实例之间,空间都是独立的(独立的内存资源)
#创建类的时候 --> 创建类对象空间 --> 类属性,类方法就在这个空间里
#实例去查找属性方法的时候 --> 先在实例空间去找 --> 找不到就去类空间去找
#创建实例的时候,会有类对象指针,通过指针来指向类空间(找到类对象的属性),但不能去修改类属性
#类不能去实例空间,它没有指针
#类空间和实例空间是相互独立的
bus03 = Bus317("湘A1111","pengyifan")
bus04 = Bus317("湘A2222","chenpeng")
print(bus03.name, bus04.name)
#结果为 pengyifan chenpeng
bus03.tmp_object_lst.append("bus03")
bus04.tmp_object_lst.append("bus04")
print(bus03.tmp_object_lst)
#结果为 ['bus03'] # 注:只有'bus03'
print(bus04.tmp_object_lst)
#结果为 ['bus04']
#它们2个相互独立,在实例化对象时,会有1个空间(对象空间),放了对象的属性和方法
#它们不属于同一个内存、对象,所在的空间不一样
bus03.tmp_class_lst.append("bus03") # 注:类空间的属性
bus04.tmp_class_lst.append("bus04")
print(bus03.tmp_class_lst, bus04.tmp_class_lst)
#结果为 ['bus03', 'bus04'] ['bus03', 'bus04']
#总结
#类 就是方法和属性总结在一起 (静态 属性,动态 方法)
#对象是类的1个实体
#创建类的时候会有1个类的命名空间,存储类中定义的属性和方法
#创建1个对象(实例)也会创建1个对象的命名空间,存放对象的属性
#obj.name 当obj对象获取name属性的时候,会先从自己的空间找name,找不到就去类中的空间找,类中找不到就去父类找,最后找不到就抛出异常
示例2:__new__方法
######__new__
#__new__创建一个实例,一般情况下 不需要重写
class Bus317(object):
#类属性
line = "317"
prod = "BYD"
#实例属性
def __init__(self, car_num, name):
#实例属性
print("init Bus317")
self.car_num = car_num
self.name = name
def __new__(cls, *args, **kwargs): # 重写的__new__实际是调用的object的__new__
print("new instance create:",cls) # 打印输出
print(args,kwargs) # cls代表的Bus317
return object.__new__(cls)
#方法 --> 行为
def run(self, flag):
if flag == 0:
print("从农大到长华小区")
else:
print("从长华小区到农大")
print(dir(Bus317))
#结果为 [……'__new__'……]
#继承object的属性和方法 里面有__new__ #一般情况下__new__不会去修改它
# 形参传参赋给 *args
bus01 = Bus317("湘A1","xull") # 实例化需要传2个参数
#结果为 new instance create: <class '__main__.Bus317'>
#('湘A1', 'xull') {}
#init Bus317
#__new__先于__init__去执行
bus02 = Bus317("湘A1",name = "xull") # 位置参数传参赋给 **kwargs
#结果为 new instance create: <class '__main__.Bus317'>
#('湘A1',) {'name': 'xull'}
#init Bus317
示例3:__new__方法
class BusChildren(Bus317):
def __init__(self):
print("init BusChildren")
def __new__(cls): # cls 当前类
print("new children:",cls)
# return Bus317.__new__(cls) # 使用Bus317的__new__方法
return super().__new__(cls) # 使用super去继承父类的__new__方法
# new instance create: <class '__main__.BusChildren'>
# 最好使用super
# return super().__new__(Bus317) # 按照Bus317 返回的是Bus317的实例
#new instance create: <class '__main__.Bus317'>
#如果实例化的instance和本省class不一致,__init__不会执行
def run(self):
print("hello children")
bus02 = BusChildren()
#结果为 new children: <class '__main__.BusChildren'>
print(type(bus02))
#结果为 <class 'NoneType'>
# print(bus02.line) #报错
#因为重写了父类的__new__所有报错(没写return)
#或者结果 new instance create: <class '__main__.BusChildren'>
#<class '__main__.BusChildren'>
#或者结果 new instance create: <class '__main__.Bus317'>
#<class '__main__.Bus317'>
# prin
print(bus02.line) # 注释掉了__new__方法 或者
#结果为 317
示例4:单例模式
######单例模式
#这个类无论实例化多少次,都是返回同一个对象实例
class Bus317(object):
#类属性
line = "317"
prod = "BYD"
obj = 0 # 注:定义属性
#实例属性
def __init__(self, car_num, name): # self是__new__创建的实例
#实例属性
print("init Bus317")
self.car_num = car_num
self.name = name
def __new__(cls, *args, **kwargs): # 注:new方法创建实例
if Bus317.obj == 0: # 注:在类里获取obj 需要接上Bus317.
Bus317.obj = object.__new__(cls) # 注:根据类 创建实例化对象 赋给obj
return Bus317.obj # 注:第二次创建直接返回 Bus317.obj
#方法 --> 行为
def run(self, flag):
print("bus317 run, %s drive" %self.name) # 注:获取属性
if flag == 0:
print("从农大到长华小区")
else:
print("从长华小区到农大")
#没修改__new__时
# bus01 = Bus317("湘A2","liweiqi")
# bus02 = Bus317("湘A3","tangliangfei")
# print(id(bus01),id(bus02)) # 注:bus01、02 不同的实例化对象
#结果为 2328728268560 2328728268752
#单例模式,初始化之后,返回的都是同一个对象
bus01 = Bus317("湘A2","liweiqi")
print(bus01.name)
#输出为 liweiqi
bus02 = Bus317("湘A3","tangliangfei")
#结果为
# init Bus317
# init Bus317
print(bus01.name,bus02.name) # 注:初始化之后,执行了2次__init__方法
#结果为 tangliangfei tangliangfei
print(id(bus01),id(bus02))
#结果为
# 2176734292864 2176734292864
#注:实例化对象 指向同一个对象
#第1次实例化后 实例空间 car_num "湘A2" name "liweiqi"
#第2次实例化后 实例空间 car_num "湘A3" name "tangliangfei"
#实例方法,静态方法,类方法
#__new__ __init__比较
总结:
__new__是实例创建以前调用的,它的任务就是创建实例,它是一个静态方法
__init__ 是当前示例创建好之后,对实例的属性进行初始化工作时运行的,它是1个实例方法
1、__new__至少有1个参数cls(可以取别的名字,没必要),代表当前类,此参数在Python解释器运行的时候自动识别 # 注:位置必须是第一个参数,代表当前类
2、__new__必须返回1个实例化对象 # 注:不返回 NoneType
3、__init__的self参数就表示__new__返回的实例,__init__在__new__的基础上做一些基础化工作,__init__不需要返回
4、子类没有定义__new__,会去找父类的__new__方法构建实例
5、新式类才有__new__ # 注:经典类没有 没有继承object类
6、如果实例化对象和本身的class不一致,__init__不会执行
7、最好不要重写__new__
练习6 创建一个学生类
创建一个学生类
·类名:Student
·属性:姓名,年龄,学校,成绩(字典)
{‘yuwen’:100, ‘suxue’:100, ‘yinyu’:100}
·方法:求总分、求平均值
#注:对于公共信息描述 可以放到类属性
示例
class Student:
school = "hunannongda" # 类属性,公共部分
def __init__(self,name,age,scores): # 初始化函数
self.name = name # 实例初始化
self.age = age
self.school = Student.school # 使用类属性的方式(使用类属性去访问)
self.scores = scores
def sum(self):
# s = 0
# for i in self.scores.values():
# s += i
# return s
return sum(self.scores.values())
def avg(self):
# s = self.sum()/len(self.scores)
# return s
return sum(self.scores.values())/len(self.scores)
scores = {"yuwen":100, "shuxue":80, "yinyu":60}
wtc = Student("wtc", "20", scores)
lxh = Student("wtc", "20", scores)
print(wtc.sum())
#结果为 240
print(wtc.avg())
#结果为 80.0
stu1 = Student("lee","18",{"语文":70,"数学":80,"英语":90})
stu2 = Student("lee1","18",{"语文":60,"数学":70,"英语":80})
print(stu1.sum())
print(stu1.avg())
#结果为
#240
#80.0
练习7 定义一个Person类
示例
#定义一个Person类
#Person属性:年龄,姓名,身份证
#行为方法: eat(输出谁在吃饭) browser(可不可以上网,18岁以上才可以上网)
import requests
class Person:
def __init__(self, age, name, id_card): # 注:单个对象的属性
self.age = age
self.name = name
self.id_card = id_card
def eat(self):
# print("%s在吃饭" %self.name)
print(f"{self.name}在吃饭")
def browser(self):
if self.age < 18:
return "不能上网"
else:
ur = requests.get("https://www.sucai8.com/")
print(ur.text)
return "可以上网"
p1 = Person(16, "tangliangfei", "1111")
p1.eat()
print(p1.browser())
#结果为 tangliangfei在吃饭
#不能上网