python-5

类和对象

 python是一个面向对象的语言,其中,几乎所有的东西都有自己的属性和方法,那就像我们可以自定义函数一样,我们可以自己定义出一种东西,而这个东西的属性和方法都是我们自己定义的。

而类 (Class) 其实相当于是我们创建对象的“蓝图”,也可以这样说,类其实是我们创建一个对象的函数,我们可以利用这个函数来创建一个对象。

创建类

 我们创建一个类,也就是创建一个可以构造一类对象的构造函数:

class aml():
    x = 5

此时我们就创建一个名为 aml 的类,里面有一个方法 x 。这个 x 的方法的意思是  如果我用了这个方法,那么我的这个对象的值就是 5 。

创建对象

 在我们创建了 我们自定义的类 之后,我们就可以用问你自定义的类来去创建对象了:

class aml():
    x = 5
    
p1 = aml()  # 此时的p1 就是我们创建的一个对象
print(p1.x)  #打印p1 的时候,我们使用 这个对象里面的 x  这个方法

输出:    5    

__init__() 函数给属性赋值

 上述的创建是最简单的类和对象的创建,我们要更好的使用类和对象,就要借助这种函数,这个函数是在类里面自定义的一个函数,这个函数可以帮我们实现更多的功能。我们之前是在这个类里面实现了这个类所能执行的方法,而这个函数可以帮我们实现这个类的属性。

每一个类都有一个__init__() 函数,这个函数在这个类启动时候执行,将值赋值给对象;                 也就是说每一次在创建这个类的对象的时候,都会自动调用这个类里面的这个函数。

class Person():
    def __init__(slef,name,age):
        slef.name = name
        slef.age = age

p1 = Person('bili','16')

print(p1.name)  #bili
print(p1.age)   #16

我们可以用这__init__函数来把我们这个对象的属性进行赋值。其中的 slef 也就是这个对象的名称。

创建方法

 我们还可以在这个类里面,创建属于这个类的方法,这个方法其实就是对应这个类的 函数。

class Person():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

p1 = Person('bili','18')

p1.Func()   #执行 p1对象的类中的 Func() 这个方法

 输出:

My name is bili ; my age is 18

 self 参数是对类的当前实例的引用,用于访问属于该类的变量。

我们也可以不用这个self 来表示这个对象的名称,这对象的名称是在函数参数列表里首元素位置,我们可以用任意的名称来表示,因为这是函数的参数嘛。但是我们在函数中,要用到这个对象的名字的时候,必须是这个函数参数的首个参数。这个首个参数就是对象的名称。

 对象的属性的操作

 修改对象属性

 当我们创建了一个对象之后,可以像下面一个修改这个对象的属性:

class Person():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

p1 = Person('bili','18')
p1.age = 15
p1.Func()   #执行 p1对象的类中的 Func() 这个方法

输出:
 

My name is bili ; my age is 15

删除对象的属性

del p1.age

这个时候 p1 中的age  这个属性就被删除掉了。

删除对象

 我们这个 del 操作不仅仅可以删除对象里面属性,还可以删除对象:

del p1

pass语句

 我们之前也说过,这个类的定义,就像是在定义一个创建对象的函数一样,那么同样的,这个类的定义中的代码块也是不能为空的,为空会报错:

class Person():

 如果这个类定义里面是空的,我们需要在这个类定义的代码块里面输入 pass语句:

class Person():
    pass

python的继承

 所谓继承就是,我们在一个类中使用继承另一个类之后,另一个类的方法和属性我们就可以使用了。

父类是继承的类,也称为基类。

子类是从另一个类继承的类,也称为派生类。

任何一个类都可以是父类,那么父类的创建就和类创建一样。

 创建子类

 要实现继承,主要还是子类的创建;当我们在创建一个类之后,像在此基础上,用其他类的属性和方法,那么就只需要在创建子类的时候,用父类作为这个子类的参数:

class Father():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

class son(Father):
    pass

p1 = son('bili','18')
p1.Func()   #执行 p1对象的类中的 Func() 这个方法

输出:

My name is bili ; my age is 18

我们发现当我们使用   子类-son来创建 p1 这个对象之后,使用了 父类-Father 当中的属性和对象操作,仍然适用。

子类__init__函数注意事项

 我们上述对于子类的创建, 子类中的内容是用 pass 跳过的,当我们需要用__init__函数定义子类的属性的时候,需要注意的是:
我们在子类中使用__init__函数定义属性之后,子类的__init__函数创建的子类,会覆盖引用的父类的__init__函数创建的属性;也就是说,我们这个时候,父类的属性将不在适用。

class Father():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

class son(Father):
    def __init__(self,name1,age1):
        self.name1 = name1
        self.age1 = age1

p1 = son('bili','18')
p1.Func()   #执行 p1对象的类中的 Func() 这个方法

我们发现此时father里属性不在适用。

如果我们想在 子类 定义 自己的属性之后,同时继承父类的属性,那么就需要在后面添加对父类__init__函数的调用:

class Father():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

class son(Father):
    def __init__(self,name1,age1):
        self.name1 = name1
        self.age1 = age1
        Father.__init__(self,name1,age1)

p1 = son('bili','18')
p1.Func()   #执行 p1对象的类中的 Func() 这个方法

 输出:

My name is bili ; my age is 18

Father.__init__(self,name1,age1)      的里面就是把 子类的 中的 self,name1,age1  这些参数都传给我的Father中的__init__函数里,在进行Father类里面 的属性定义。

使用 super() 函数

我们上述是使用,在子类 中 定义 自己的属性的时候,在后面添加 父类 属性的 引用。除了这个方式之外,在python中还有一个函数--- super()函数,这个函数使用之后,可以是 子类 继承 父类的方法和属性。

class Father():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

class son(Father):
    def __init__(self,name1,age1):
        self.name1 = name1
        self.age1 = age1
        super().__init__(name1,age1)

p1 = son('bili','18')
p1.Func()   #执行 p1对象的类中的 Func() 这个方法

 输出:

My name is bili ; my age is 18

我们看上述的倒数第三行代码,我们这样子使用这个  super() 函数之后就可以达到  这个句代码相同的功能---  Father.__init__(self,name1,age1)   ----。我们super后面__init__ 函数里的参数,不用传 对象的名称,只需要把 父类 中的属性传入即可,这就把父类里面的属性拷贝过来。

在使用super()函数的时候不必在  加上父类的名字,它将自动的从其父类 中 继承方法和属性。

添加属性

在里面son 类里面 新加一个Myyear的属性:

class Father():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

class son(Father):
    def __init__(self,name1,age1):
        self.name1 = name1
        self.age1 = age1
        Father.__init__(self,name1,age1)
        self.Myyear = 2022

p1 = son('bili','18')
print(p1.Myyear)   #输出:    2022

如果再次当中我们的 2022 应该是一个变量,而且在创建 p1 对象的时候,应该传入这个参数:

class Father():
    def __init__(Myself,name,age):
        Myself.name = name
        Myself.age = age

    def Func(Youself):
        print(f'My name is {Youself.name} ; my age is {Youself.age}')

class son(Father):
    def __init__(self,name1,age1,year):
        self.name1 = name1
        self.age1 = age1
        Father.__init__(self,name1,age1)
        self.Myyear = year

p1 = son('bili','18','2022')
print(p1.Myyear)   #输出:    2022

在定义的 类函数之外也可以添加属性:

class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def Func(self,name,age):
        print(f'My name is {name} ; My age is {age}')

Per.year = 2022    #在Per 类里面创建一个 year 属性
p1 = Per('li si','18')
p1.Func('zhang san','22')   # 输出: My name is zhang san ; My age is 22
print(p1.year)  # 输出:    2022

这是为类创建 属性,我们也可以 单独为一个对象创建一个新的属性:

class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def Func(self,name,age):
        print(f'My name is {name} ; My age is {age}')

p1 = Per('li si','18')
p1.year = 2022
print(p1.year)  # 输出:    2022

我们这一次操作就是在 p1 这个对象中插入 year 这个属性,注意是单独为 p1 这个对象插入属性,其他同类对象是不可用的:
 

class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def Func(self,name,age):
        print(f'My name is {name} ; My age is {age}')

p1 = Per('li si','18')
p1.year = 2022
print(p1.year)  # 输出:    2022

p2 = Per('zhang san','20')
print(p2.year)

 delattr()方法 和 setattr()方法

除此之外,我们还可以使用  delattr 方法来删除 某个对象中的某个属性,格式:
 

delattr(对象名,'要删除的属性名')

需要注意的是,属性名是一个字符串,要用字符串的规则 括起来,具体示例:

class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def Func(self,name,age):
        print(f'My name is {name} ; My age is {age}')

p1 = Per('li si','18')
p1.year = 2022

delattr(p1,'name')
print(p1,name)

这个时候 p1 对象中的name 属性已经不在了,我们在使用这个属性就会报错:

 setattr 方法 可以帮我们 在某一个 对象里面创建一个属性,他的语法规则是:

setattr(对象名,'需要创建的属性名','属性需要赋的值')

具体示例:

class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def Func(self,name,age):
        print(f'My name is {name} ; My age is {age}')

p1 = Per('li si','18')
p1.year = 2022

delattr(p1,'name')
#  hasattr  为判断某个对象中 的某个 属性是否存在的函数
#  存在就返回 True  不存在就返回 false
print(hasattr(p1, "name"))    #False  说明这个时候 p1 里面没有 name 这个属性

setattr(p1,'name','wang wu')
print(hasattr(p1, "name"))   #True  说明此时 p1 里面有了 name 这个属性

 MethodType 方法 给对象添加方法

 MethodType  方法的使用需要 import 这个MethodType。MethodType 的格式:

MethodType(方法名,对象名)

 具体示例;

from types import MethodType
class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

def Func(self,name,age):
    print(f'My name is {name} ; My age is {age}')

p1 = Per('li si','18')
p1.Func = MethodType(Func,p1)
p1.Func('zhangsan','18')     #My name is zhangsan ; My age is 18

我们可以看到,此时在  Per  类之外定义的 Func 函数(方法) ,   已经可以被我们的 p1 所调用了。

 迭代器

 迭代器是一种特殊的对象,它可以记住每一次迭代之后,所遍历的位置,下一次迭代的时候就从这个位置开始下个位置进行迭代,直到迭代完这里面的数据为止。也就是说,迭代器只会往前不会后退。

可迭代对象

 我们把可以从 for循环这类语句中中 读取一个元素的给我们使用的 对象,称为可迭代对象。

我们可以使用 isinstance  方法来帮助我们判断一个对象是否为 可迭代对象,这个方法使用来判断一个对象是否是某个类型的方法,如果是就返回 True ; 不是就返回 False,语法规则:

isinstance( 对象名 , 类型名 )
class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def Func(self,name,age):
        print(f'My name is {name} ; My age is {age}')

class son():
    def __init__(self,name,age):
        self.name = name
        self,age = age

p1 = Per('li si','18')
p2 = son('wangwu','20')

print(isinstance(p1,Per))  #True
print(isinstance(p2,Per))  #False

print(isinstance(p1,son))  #False
print(isinstance(p2,son))  #True

我们可以用这样的方式来判断一个对象是不是 可迭代对象:

注:Iterable 对象 需要 引用 :from collections.abc import Iterable    或者  from collections import Iterable  

from collections.abc import Iterable
class Per():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def Func(self,name,age):
        print(f'My name is {name} ; My age is {age}')

class son():
    def __init__(self,name,age):
        self.name = name
        self,age = age

p1 = Per('li si','18')
p2 = son('wangwu','20')

print(isinstance(p1,Iterable))   #Fasle
print(isinstance(p2,Iterable))   #Fasle

我们发现我们创建的两个类的对象 都不是可迭代对象。

迭代器 VS 可迭代对象(Iterable)

 在python中 列表、元组、字典和集合这些都是可迭代的对象。它们是可迭代的容器,我们可以从中获取迭代器(Iterator),

这些可迭代对象里面都有一个 可以获取这可迭代对象的迭代器的方法  iter()函数

list = ('hello','world','lisi')
myit = iter(list)

此时我们就用 iter 方法把 list 的这可迭代对象的 迭代器 取出来 给到 myit 中了,此时我们myit 就是list的 迭代器,此时我们打印 myit 类型发现 myit 的类型是迭代器 这种特殊类型:

print(type(myit))

 输出:

print(type(myit))

 此时我们可以利用这个 myit 迭代器 在用 next() 函数  来输出 list 这里面的值:

list = ('hello','world','lisi')
myit = iter(list)

print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))

输出:

hello
world
lisi

 当我们的next() 访问到 myit 的最后一个数据之后一个数据的时候 ,他会提示 抛出异常 ,来提醒我们这个 myit 里的数据访问完了。

list = ('hello','world','lisi')
myit = iter(list)

print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))

同样的,只要是可迭代对象里面获取出来的 迭代器都是可以使用 next ()函数的:

list = 'abcdefg'
myit = iter(list)

for i in range(0,7):
    print(next(myit))

: 输出结果

 迭代器也可以作为可迭代对象,所以我们可以用for循环,把他作为一个可迭代对象来回使用:
 

list = ('hello','world','lisi')
myit = iter(list)

for i in myit:
    print(i)

 输出:

hello
world
lisi

 当我们直接用for遍历打样字符串 的时候 ,for循环其实是 帮我们创建了一个 迭代器 ,然后每一次循环使用 next()函数就行访问操作。

mystr = "banana"

for x in mystr:
  print(x)

创建迭代器

 我们之前说过迭代器其实就是一种对象,那么我们如何创建一个迭代器?

要把对象/类创建为迭代器,必须为对象实现 __iter__()  __next__() 方法,

__iter__()  的实现和 __init__ 函数试下类似 ,我们可以在这个函数里实现一些操作,但是必须一直返回迭代器本身。

__net__() 同样允许我们执行一些操作(初始化等等),但是必须指向这个列表里面下一个项目。

例:我们实现一个 数字的迭代器,从1 开始 ,每个序列都增加1(即:返回 1  2  3  4  5  6  等等)

class Per():
    def __iter__(self):
        self.num = 1
        return self

    def __next__(self):

        num1 = self.num
        self.num += 1
        return num1


p1 = Per()
mytier  = iter(p1)

print(next(p1))
print(next(p1))
print(next(p1))
print(next(p1))
print(next(p1))
print(next(p1))

如此我们就打印了 1~6:

 StopIteration

 我们发现,上面我打印 1~6  有点憨憨的,那么像之前我们用过 for 循环来 结合 迭代器来打印过 某个列表里面的内容,那么我们的这个 自定义的迭代器能不能用for循环呢?

答案是 yes ,但是会出现一些问题:

class Per():
    def __iter__(self):
        self.num = 1
        return self

    def __next__(self):
   
        num1 = self.num
        self.num += 1
        return num1
        

p1 = Per()
mytier  = iter(p1)

for i in mytier:
    print(i)

 我们发现这个程序无休止的循环 ~~~~,这是因为我们没有给他的循环设置条件,而这个条件不光光可以再循环里面设置,还可以在我们 定义的 迭代器 中实现。

class Per():
    def __iter__(self):
        self.num = 1
        return self

    def __next__(self):
        if self.num <= 5:
            num1 = self.num
            self.num += 1
            return num1
        else:
            raise StopIteration

p1 = Per()
mytier  = iter(p1)

for i in mytier:
    print(i)

这个当中 的 __next__() 中,我们加了一个 if 条件判断  就限制这个迭代器只能迭代到 5  ,那么如果超出 5 了就是 else 里面语句:

如果你有足够的 next() 语句,或者在 for 循环中使用,则上面的例子将永远进行下去。

为了防止迭代永远进行,我们可以使用 StopIteration 语句。

在 __next__() 方法中,如果迭代完成指定的次数,我们可以添加一个终止条件来引发错误

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chihiro1122

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

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

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

打赏作者

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

抵扣说明:

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

余额充值