19_python笔记-面向对象1


博客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在吃饭
#不能上网
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值