20_python笔记-面向对象2


博客cpen_web

练习1 类的使用

·已经有Bus317这个类
·实例化一个对象 # 注:通过__new__方法创建的实例(一般不要重写)
·使用对象的属性
·使用对象的方法
·添加实例属性 # 注:没有就添加 有就修改
·修改实例属性
·添加类属性
·修改类属性
·删除属性

示例

# 类的使用
class Bus317(object):
    line = "317"
    prod = "BYD"
    obj = 0     # 注:定义属性
    def __init__(self, car_num, name):
        # print("init Bus317")
        self.car_num = car_num
        self.name = name
    def run(self, flag):
        print("bus317 run, %s drive" %self.name)
        if flag == 0:
            print("从农大到长华小区")
        else:
            print("从长华小区到农大")

# 实例化对象
bus01 = Bus317("湘A2","甲")
# 使用对象的属性
print(bus01.car_num)
# 使用对象的方法
bus01.run(0)
# 添加实例属性			# 注:实例空间 使用实例名字访问
bus01.time = "1h"
# 修改实例属性
bus01.name = "乙"
# 添加类属性			# 注:类空间 使用类名访问
Bus317.company = "changsha_bus"
# 修改类属性
Bus317.line = "10"
# 删除属性
delattr(Bus317, "line")		# 注:删除Bus317的line属性
del Bus317.line			# 注:删除索引

#注:删除属性
#方法1、delattr(Bus317, "line")		# 注:删除Bus317的line属性
#方法2、del Bus317.line				# 注:删除索引

练习2 斐波拉契数列

#注:用类实现斐波那契数列的运算(编写自定义迭代器)

方法1:生成器实现斐波拉契数列

示例

#生成器实现斐波拉契数列
def fib():  # 注:定义生成器函数
    pre,cur = 0,1    # 注:初始化值
    while True:     # 注:循环获取
        yield cur    # 注:yield 获取
        pre, cur = cur, pre+cur
f = fib()
#使用列表推导式
print([ next(f) for i in range(20)])
#结果为 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
#注:循环获取20个值 使用列表推导式

方法2.1:迭代器实现斐波拉契数列

示例

#迭代器实现斐波拉契数列
class Fib():
    def __init__(self):
        self.pre = 0
        self.cur = 1

    def __iter__(self):
        return self

    def __next__(self):
        result = self.cur
        self.pre, self.cur = self.cur, self.cur+self.pre
        return result

f = Fib()   # 注:进行实例化对象
print([next(f) for i in range(20)])
#结果为 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

方法2.2:迭代器实现斐波拉契数列

示例

#迭代器实现斐波拉契数列
class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b
        return self.a

    def __iter__(self):
        return self

f = Fibs()
print([next(f) for i in range(20)])
#结果为 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

知识点3 类-self详解

#总结
#self在定义实例方法时,需要定义,调用时自动传如
#self的名字并不是规定死的,但是 最好还是按照约定使用self
#self总是指向调用时的类的实例

#方法:判断使用类去执行,还是使用对象执行
# 看有没有self
# 有self,使用实例对象执行
# 没有self,使用类执行

示例1:self代表的是类的实例,而并非类

#1、self代表的是类的实例,而并非类
class Person():
    name = "wy"
    age = 18

    def info(self):
        print(f"我是:{self.name},今年{self.age}岁了") # 定义类属性
        print(self) # 注:self代表类的实例(而非类) Person object
        print(self.__class__)   # 注:查看属于哪个类
p = Person()    # 对Person类进行实例化
p.info()        # 进行实例化方法
#结果 我是:wy,今年18岁了
# <__main__.Person object at 0x0000023C8D6865B0>
# <class '__main__.Person'>

示例2:self不必非写成self

#2、self不必非写成self
#实例方法 第1个参数不必非写成self
#约定俗成都使用self
class Person():
    name = "wy"
    age = 18

    def info(this): # 注:运行时自动识别第1个参数,当做它的对象
        print(f"我是:{this.name},今年{this.age}岁了")
        print(this)
        print(this.__class__)
p = Person()
p.info()
#结果 我是:wy,今年18岁了
# <__main__.Person object at 0x0000023C53656B80>
# <class '__main__.Person'>

示例3:self可以不写

#3、self可以不写
#但就不是1个实例方法了,属于1个类方法
class Person():
    name = "wy"
    age = 18

    def info(this):
        print(f"我是:{this.name},今年{this.age}岁了")
        print(this)
        print(this.__class__)
    def info2():    # 注:self可以不写
        print("this is info2")
p = Person()
p.info()    # --> Person.info(p)
#当调用p.info()时,实际上Python解释器解释成Person.info(p)去运行的

# p.info2()       #注:报错 不可以使用实例化对象去运行
#执行的时候 --> Person.info2(p)     info2()需要0个位置参数 但是给了1个位置参数
#TypeError: info2() takes 0 positional arguments but 1 was given

Person.info2()  # 注:使用类方法去运行
#结果为 this is info2

# Person.info()   # 注:报错
#TypeError: info() missing 1 required positional argument: 'this'

Person.info(p)
#结果为 我是:wy,今年18岁了
# <__main__.Person object at 0x000001DC390765B0>
# <class '__main__.Person'>

示例4:在继承的时候,self代表实例

#4、在继承的时候,self代表哪个类
#self就代表那个实例,无论怎么继承
class Parent:
    def pprt(self):
        print(self)
class child(Parent):
    def cprt(self):
        print(self)

c = child()
c.cprt()    # 注:self代表c对象 实例化对象
#结果为 <__main__.child object at 0x00000228AFDB6B80>
c.pprt()    # 注:继承的父类的方法 self还是代表实例(c对象)
#结果为 <__main__.child object at 0x00000228AFDB6B80>
p = Parent()
p.pprt()    # 注:self代表实例本身(p对象)
#结果为 <__main__.Parent object at 0x0000018578C96970>

知识点4 类的继承

面向对象的好处
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。	# 注:继承实现代码的复用
·可以节省很多的代码,不需要写,直接使用			# 注:继承的好处
·衍生出不同的子类,大部分代码一样,部分代码不一样	# 注:继承的好处

练习5 类的继承

·创建一个父类:Animal
·创建子类:Person、Pig
·定义属性category及统计数量
·在父类中定义方法breath
·测试:实例化,检查数量统计情况、检测实例与类的关系

示例

class Animal():
    category = "Animal" # 类属性
    count = 0
    def __init__(self): # 初始化
        self.name = "animal"
        self.age = "18"
        print("初始化animal")
        Animal.count += 1
        print(Animal.count)
    def breath(self):
        print("i can breath")
    def eat(self):
        print("i can eat")

class Person(Animal):   # 子类
    count = 0
    category = "person"
    def __init__(self): # *注:子类重写父类的方法
        print("初始化Person")
        Person.count += 1
        print(Person.count)
    def eat(self):
        print("person is eating...")

class Dog(Animal):
    def eat(self):
        print("dog is eating...")

class Pig(Animal):
    count = 0
    def __init__(self): # 注:在父类的初始化后,又重加了一些属性
        # self.name = "pig"
        print("初始化pig")
        super().__init__()  # 注:python3的语法;无论是什么父类
        # super(Pig, self).__init__() # 注:Python2、3都支持的语法 ;self必须是Pig的实例 super必须只能去访问父类
        # Animal.__init__(self) # 需要明确父类
        self.name = "pig"
        Pig.count += 1
        print(Pig.count)
        #super 一般在子类里面使用,去访问父类的东西的时候 才会用到

#实例化对象
animal = Animal()
#结果为 初始化animal
#1
person = Person()   # 注:子类继承父类的__init__,重写了__init__,使用自己的__init__
#结果为 初始化Person
#1
dog = Dog()         # 注:子类会继承父类的所有方法,包括__init__,子类没有重写 会使用父类父类的__init__
#结果为 初始化animal
#2

# pig = Pig()
#结果为 初始化pig
#初始化animal
#3

pig = Pig()
#结果为 初始化pig
# 初始化animal
# 3
# 1

# print(pig.name)   # 注:注意super()和self.name = "pig"的位置
#结果为 animal

print(pig.name, pig.age)     # 注:super()写在self.name = "pig"前面
#结果为 pig 18

#注:Pig继承Dog,Dog继承Animal,super.__init__(self) 不接参数访问dog的__init__,但直接指定super(Animal).__init__(self) 访问不到Animal的__init__

#示例:重写父类的方法
#重写父类的方法
animal.eat()
#结果为 i can eat
dog.eat()   # 重写Animal的eat
#结果为 dog is eating...
pig.eat()   # 继承Animal的eat
#结果为 i can eat

#示例:类和实例的关系
#注意类和实例的关系
#注:isinstance判定它属于哪个类
print("isinstance(animal,Animal)",isinstance(animal,Animal))
#结果为 isinstance(animal,Animal) True
#注:animal属于Animal类
print("isinstance(pig,Animal)",isinstance(pig,Animal))
#结果为 isinstance(pig,Animal) True
#注:pig属于Animal类 ;pig属于Pig类,也属于Animal类
print("isinstance(animal,Pig)",isinstance(animal,Pig))
#结果为 isinstance(animal,Pig) False
#注:小类属于大类,大类不属于小类

练习6 自定义异常类

自定义异常类:
·自定义异常能让异常更精准
·自定义异常类:当list内元素长度超过10的时候抛出异常
·自定义异常类:消息小于8时抛出异常

示例1

try:
    a = 1/0
except Exception as e:
    print("exception error")
#结果为 exception error
#-------------------------------------------------------------------------------------------
#自定义异常类
class ListError(Exception): # 注:继承Exception的基类
    def __init__(self,lst,message): # 注:重写Exception异常类的__init__方法
        self.list = list            # 注:不写的话调用的是Exception异常类的__init__方法
        self.message = message
    # pass              # 注:不写的话直接pass
    def __str__(self):  # 注:对listError的说明
        return "list 长度不在8-10之间"
# print(ListError())
# #结果为 list 长度不在8-10之间
    def __str__(self):  # 注:重写exception的str方法,获得异常类信息
        msg = "list:"+str(self.list)
        msg = msg +"\n"+self.message
        return msg
try:
    lst = [1,2,3,4,5,6,7,8,9,0,11]
    if not 8<len(lst)<10:
        # raise ListError("长度不在8-10之间") # 注:exception帮你做了
        # raise ListError()
        raise ListError(lst, "长度不在8-10之间")

except ListError as e:
    print("ListError error:",e)
#结果为 ListError error: 长度不在8-10之间
#结果为 ListError error: list 长度不在8-10之间

示例2

#自定义异常类##########
class ListError(Exception):
    def __init__(self,list, message):  #重写Exception异常类的__init__方法
        self.list = list		# 注:目的是重写输出信息
        self.message = message
    # pass
    def __str__(self):   #重写Exception的str方法,获得异常类信息
        msg = "list:"+str(self.list)
        msg = msg +"\n" +self.message
        return msg
#print(ListError())
try:
    lst = [1,2,3,4,5,6,7,8,9,0,11]
    if not 8<len(lst)<10 :
        raise ListError(lst,"长度不在8-10之间")
        # raise ListError(lst,"长度不在8-10之间","xx","yy")
except ListError as  e:
    print("listError error:",e)
#结果为 listError error: list:[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11]
#长度不在8-10之间

#结果为 listError error: ([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11], '长度不在8-10之间', 'xx', 'yy')

练习7 接收从键盘的输入,如果输入字符中包含了除数字以外的字符,就抛出自定义异常

示例

#接收从键盘的输入,如果输入字符中包含了除数字以外的字符,就抛出自定义异常
class IsNumber(Exception):

    def __init__(self,str1,message):
        self.str1 = str1
        self.message = message
    def __str__(self):  # 仅仅只是打印 *args, **kwargs
        msg = "\n"+self.str1+"\n"+self.message
        return msg
a = input("请输入一串:")
try:
    if not a.isdigit(): # 把一串接收的参数作为元组打印(可变长位置参数) 字典(可变长关键字参数)
        raise  IsNumber(a,f"{a}中存在除数字之外的东西")    # 注:抛出异常
except IsNumber as e:
    print("IsNumber error",e)
#结果为 请输入一串:123abc
#IsNumber error
#123abc
#123abc中存在除数字之外的东西

知识点8 Python中的多态

#多态:同一种事物的多种形态
#多态:* 实现接口的重用

示例

#Python的多态
#Python里不支持多态,Python处处是多态

#Python动态解释型语言
#1、Python
# def func1(name):
#     print(name)
# func1("wy")

#2、java
# def func1(str name) # 注:定义类是str类型,传递的必须是str类型
#java里先对obj进行类型判断(对传递的类型严格把控)
#java里面使用继承,类型指定为A类,传递参数
#Java中使用继承实现多态

#-------------------------------------------------------------------------------------------
class A:
    def func1(self):
        print("class A func1")

# class B(A):
class B():
    def func1(self):
        print("class B func1")

# class C(A):
class C():
    def func1(self):
        print("class C func1")

def func2(obj): # 注:func2() 接收的对象只要有func1()方法,就可以被正确执行
    obj.func1() # 注:只要有func1()方法的参数,都可以去执行它
		# 注:Python里崇尚鸭子类型,不管这个obj对象是什么类,只要有func1()行为
a1 = A()
# a1.func1()
b1 = B()
# b1.func1()
c1 = C()
func2(a1)
func2(b1)
func2(c1)
#结果为 class A func1
# class B func1
# class C func1

#为什么说不支持多态:不需要像java一样以父类作为参数传递子类的对象()
#为什么说处处是多态:按照python的表现力来说处处是多态

#Python里处处是多态:因为 本身就实现了多态的性质
#Python里不支持多态:因为 按多态的严格语法来说 父类作为参数,可以传递子类对象

知识点9 经典类与新式类

类可以多重继承
定义类A
定义类B\C,B\C继承自A # 注:多重继承 A继承B B继承C
定义类D, D继承自B
定义类E, E继承自C
定义类F, F继承自D\E

示例1:python 类可以多重继承

#python 类可以多重继承
class A:
    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")
class E(C):
    def test(self):
        print("from E")

class F(D,E):
    def test(self):
        print("from F")

f = F()
f.test()
#结果为 from F

示例2:经典类与新式类在类型上的区别

#注:tmux 同步
#注::set synchronize-panes  on	(操作:[ctrl + b  (shif +):]set syn[tab键 补齐])
#注:off 是 关闭

#-------------------------------------------------------------------------------------------
#Python2
>>> class A(): pass	# 注:经典类
... 
>>> class B(): pass
>>> a = A()
>>> b = B()
>>> type(a)			# 类的实例都是instance类型;属于instance(代表所有实例)
<type 'instance'>		# 经典类里都统称为 实例
>>> type(b)
<type 'instance'>
>>> type(a) == type(b)
True
>>> a.__class__		# 注:__class__查看对象属于哪个类
<class __main__.A at 0x7ff46ddce258>	# 注:经典类 类与实例只有通过__class__属性进行关联
>>> b.__class__
<class __main__.B at 0x7ff46ddce2c0>
#-------------------------------------------------------------------------------------------
#Python3
>>> class A(): pass	# 注:新式类
... 
>>> class B(): pass
... 
>>> a = A()
>>> b = B()
>>> type(a)			# 属于新式类
<class '__main__.A'>	# 新式类实例化对象 type出来的对象都属于某一个类
>>> type(b)
<class '__main__.B'>
>>> type(a) == type(b)
False
>>> a.__class__		# 注:__class__查看对象属于哪个类
<class '__main__.A'>
>>> b.__class__
<class '__main__.B'>
#总结:
#经典类和新式类
1、类型区别
·经典类
·所有的类都是classobj类型,而类的实例都是instance类型。
·类与实例只有通过__class__属性进行关联
·新式类
·类实例的类型是这个实例所创建自的类(通常是和类实例的__class__相同)
2、继承顺序
经典类:深度优先
新式类:广度优先
#广度优先 查找顺序 F --> D --> B --> E --> C --> A

示例3

class A():
    def talk(self):
        print("A")

class B(A):
    pass
    #def talk(self):
    #    print("B")

class C(A):
    def talk(self):
        print("C")

class D(B,C):   #注:D 继承 B和C(这注释写在python2中报错)
    pass
    #def talk(self):
    #    print("D")

d1 = D()
d1.talk()
#-------------------------------------------------------------------------------------------
[root@cPen_centos8 lianxi]# python2 test_class.py 	# 注:深度优先 经典类
A
[root@cPen_centos8 lianxi]# python2 test_class.py 	# 注:广度优先 新式类
C

示例4

#python 类可以多重继承(这注释写在python2中报错)
class  A:
    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")
class  E(C):
    def test(self):
        print("from E")
class F(D,E):
    def test(self):
        print("from F")
f = F()
f.test()
#-------------------------------------------------------------------------------------------
[root@cPen_python lianxi]# python2 test_class2.py 
from F
[root@cPen_python lianxi]# python3 test_class2.py 
from F

#注:经典类 python2 深度优先,一条路走到黑(从左到右 从下到上)
#注:新式类 python3 广度优先,先把子类对象找完,再去找另外1边, 不会直接去找父类
#注:广度优先 寻找到每1边的父类为止
#注:广度优先 先找1边的所以子类,再找另一边的所以子类
#广度优先 查找顺序 F --> D --> B --> E --> C --> A


#class F(D,E,B)	#注:只能先继承父亲,再继承爷爷
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

mycpen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值