python面向对象进阶

python面向对象进阶

1.成员

面相对低昂中的所有成员:

  • 变量
    • 实例变量
    • 类变量
  • 方法
    • 绑定方法
    • 类方法
    • 静态方法
  • 属性

1.1变量

  • 实例变量,属于对象,每个对象中各自维护自己的数据
  • 类变量,属于类,可以被所有的对象共享,一般用于给对象提供公共数据(类似于全局变量)
    在这里插入图片描述

类变量实例

当把每个对象中都存在的相同的实例变量时,可以选择把它放在类变量中,可以避免对象中维护多个相同的数据

class Person:
    country="中国"
    def __init__(self,name):
        self.name=name
    def show(self):
        message="我叫{},我在{}".format(self.name,self.country)
        print(message)
p=Person("wxy")
print(p.name)#wxy
#通过对象调用变量
print(p.country)  #中国
p.show()  #我叫wxy,我在中国
#通过类调用变量
print(Person.country)  #中国

易错点

  • 读和写的区别
    在这里插入图片描述
#读
class Person:
    country="中国"
    def __init__(self,name):
        self.name=name
    def show(self):
        message="我叫{},我在{}".format(self.name,self.country)
        print(message)
p=Person("wxy")
print(p.name)#wxy
#通过对象调用变量
print(p.country)  #中国
p.show()  #我叫wxy,我在中国
#通过类调用变量
print(Person.country)  #中国
#写1
class Person:
    country="中国"
    def __init__(self,name):
        self.name=name
    def show(self):
        message="我叫{},我在{}".format(self.name,self.country)
        print(message)
p=Person("wxy")
print(p.name)#wxy
#通过对象调用变量
print(p.country)  #中国
p.show()  #我叫wxy,我在中国
#通过类调用变量
print(Person.country)  #中国
#写2
class Person:
    country="中国"
    def __init__(self,name):
        self.name=name
    def show(self):
        message="我叫{},我在{}".format(self.name,self.country)
        print(message)
#Person.country修改的是类中country的值
Person.country="安徽"
p=Person('wxy')
#country已被修改
print(p.country)
# 安徽
  • 继承关系中的读写
    在这里插入图片描述
class Base(object):
    country = "中国"
class Person(Base):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        # message = "{}-{}-{}".format(Person.country, self.name, self.age)
        message = "{}-{}-{}".format(self.country, self.name, self.age)
        print(message)
# 读
print(Base.country) # 中国
print(Person.country) # 中国

obj = Person("wxy",19)
print(obj.country) # 中国
obj.show()

# 写
Base.country = "china"
Person.country = "泰国"
obj.country = "日本"

1.2方法

  • 绑定方法,默认有一个self参数,由对象进行调用(此时self就等于调用方法的这个对象)【对象&类均可调用】

  • 类方法,默认有一个cls参数,用类或对象都可以调用(此时cls就等于调用方法的这个类)【对象&类均可调用】

  • 静态方法,无默认参数,用类和对象都可以调用【对象&类均可调用】

    在python中比较灵活,方法都可以通过对象和类调用;而在java,c#等语言中,绑定方法只能由对象调用,类方法或静态方法只能由类调用

class Foo:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def f1(self):
        print("绑定方法",self.name)
    @classmethod
    def f2(cls):
        print("类方法",cls)
    @staticmethod
    def f3():
        print("静态方法")
#绑定方法对象
f=Foo("wxy",18)
f.f1()  #绑定方法经常通过对象调用
Foo.f1(f)

#类方法
Foo.f2() #cls就是当前调用这个方法的类(类方法经常通过类调用)
f.f2()  #cls就是当前调用这个方法的对象的类

#静态方法
Foo.f3()  #类执行方法(静态方法经常通过类调用)
f.f3()  #对象执行方法

1.3属性

属性其实就是有绑定方法+特殊装饰器组合创造出来的,让我们在调用方法是不用加括号

class Foo:
    def __init__(self,name):
        self.name=name
    @property
    def f1(self):
        return 123
f=Foo('wxy')
#被属性装饰的方法,直接加方法名,不用加()
result=f.f1
print(result) #123

属性编写有两种方式

  • 方式一,基于装饰器

    class C:
        @property
        def x(self):
            print("property")
        @x.setter
        def x(self,value):
            print(value)
        @x.deleter
        def x(self):
            pass
    
    o=C()
    a=o.x
    print(a)
    o.x=123
    del o.x
    
  • 方式二,基于定义变量

    class C:
        def getx(self):
            print('getx')
        def setx(self,value):
            print('setx')
        def delx(self):
            print('delx')
        x=property(getx,setx,delx,"I'm the 'x' property.")
    c=C()
    #调用getx
    c.x
    #调用setx,将值传递给value
    c.x=123
    # 调用delx
    del c.x
    

    由于属性和实例变量的调用方式相同,所以在编写时要注意:属性名称不要和实例变量重名,一旦重名,可能会报错

    如果想在名称上创建一些关系,可以在实例变量上加一个下划线

    class Foo:
        def __init__(self,name):
            self._name=name
    
        @property
        def name(self):
            return self._name
    o=Foo('wxy')
    #调用类变量
    print(o._name)
    #调用类方法
    print(o.name)
    

2.成员修饰符

python中成员的修饰符就是指:共有,私有

  • 共有,在任何地方都可以调用这个成员
  • 私有,只有在类的内部才可以调用该成员(成员是以两个下划线开头,则表示该成员为私有)

示例一:私有变量

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

    def get_data(self):
        #私有变量可以在类中使用
        return self.__name
    def get_age(self):
        return self.age

o1=Foo('wxy',18)
#共有成员
print(o1.age)
print(o1.get_age())
#'Foo' object has no attribute '__name'
print(o1.__name)  #私有变量外部不能调用,会报错,只能在类中进行使用
#调用私有成员
v=o1.get_data()
print(v)

示例二:私有方法

class Foo:
    def get_age(self):
        print("共有方法get_age")
    def __get_data(self):
        print("私有方法__get_data")
    def proxy(self):
        print("共有方法proxy")
        #私有方法可以在类中使用
        self.__get_data()
o=Foo()
o.get_age()
o.proxy()
o.__get_data()#报错,私有方法不能再外部使用
# 共有方法get_age
# 共有方法proxy
# 私有方法__get_data

示例三:属性+私有方法

class Foo:
    @property
    def __name(self):
        print("私有的name")
    @property
    def proxy(self):
        print("共有的proxy")
        self.__name
        return 1

o=Foo()
v=o.proxy
print(v)
# 共有的proxy
# 私有的name
# 1

提示:父类中的私有成员,子类无法继承

class Base:
    def __data(self):
        print("base.__data")
    def num(self):
        print('base.num')
class Foo(Base):
    def func(self):
        #自己没有找父类
        self.num()
        #'Foo' object has no attribute '_Foo__data'
        #自己没有找父类,父类中是私有方法,不能使用,所以报错
        self.__data()
o=Foo()
o.func()
#这样调用可以
class Base:
    def __data(self):
        print("base.__data")
    def num(self):
        print("base.num")
        #可以调用自己的私有方法
        self.__data()
class Foo(Base):
    def func(self):
        self.num()
o=Foo()
o.func()
# base.num
# base.__data

用一些特殊的语法也可以被外部调用【不推荐这样写】

class Foo:
    def __init__(self):
        self.__num=123
        self.age=19

    def __msg(self):
        print(123)
o=Foo()
print(o.age)
#通过对象._方法名__私有变量名可以调用私有变量
print(o._Foo__num)
#通过对象._方法名__私有方法名可以调用私有方法
o._Foo__msg()

判断什么时候创建私有和共有

  • 判断是否可以作为独立的功能暴露给外部,让外部调用并使用
  • 可以,用共有。不可以,放在内部给其他方法辅助,私有

3.对象嵌套

组合,关联,依赖等(java的称呼),即各种嵌套

4.特殊成员

在python的类中存在一些特殊的方法,这些方法都是__init__格式,这种方法在内部均有特殊含义

  • __init__,初始化方法

    class Foo:
        #创建对象时,自动执行
        def __init__(self,name):
            self.name=name
    o=Foo('wxy')
    
    
  • __new__,构造方法

    class Foo(object):
        def __init__(self,name):
            print("第二步,初始化对象")
        #没有创建这个方法,会去默认父类object中找
        def __new__(cls, *args, **kwargs):
            print("第一步,创建对象返回")
            return object.__new__(cls)
    o=Foo('wxy')
    # 第一步,创建对象返回
    # 第二步,初始化对象
    
  • __call__

    class Foo(object):
        def __call__(self, *args, **kwargs):
            print("执行call方法")
    o=Foo()
    #对象(),自动执行call方法
    o()
    
  • __str__

    class Foo:
        #返回值是字符串类型
        def __str__(self):
            return '你好'
    o=Foo()
    data=str(o)
    print(data)
    #你好
    
  • __dict__

    class Foo:
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
    o=Foo('wxy',18)
    #返回字典类型
    print(o.__dict__)
    # {'name': 'wxy', 'age': 18}
    
    
  • __getitem__,__setitem__,__delitem__

    class Foo:
        def __getitem__(self, item):
            pass
        def __setitem__(self, key, value):
            pass
        def __delitem__(self, key):
            pass
    a=Foo()
    a['x1']=123
    a['x2']=123
    b=a['x1']
    print(b)
    del a['x2']
    
    
    
  • __enter__,__exit__

    class Foo:
        def __enter__(self):
            print("进入")
            return 666
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("出去了")
    f=Foo()
    #data是返回值
    #上下文管理语法
    with f as data:
        print(data)
    

    应用场景:数据库连接

    1. 连接=连接数据库

    2. 操作数据库

    3. 关闭数据库

      class SqlHelper(object):
      
          def __enter__(self):
              self.连接 = 连接数据库
              return 连接
      
          def __exit__(self, exc_type, exc_val, exc_tb):
              self.连接.关闭
             
      with SqlHelper() as 连接:
          连接.操作..
      
  • __add__

    class Foo:
        def __init__(self,name):
            self.name=name
        def __add__(self, other):
            return '{}-{}'.format(self.name,other.name)
    v1=Foo('wxy1')
    v2=Foo('wxy2')
    #对象+值,内部会执行,对象.__add__方法,并将+后面的值当参数传递过去
    v3=v1+v2
    print(v3)
    # wxy1-wxy2
    
    
  • __iter__

    • 迭代器定义
      • 当类中定义了__iter____next__两个方法
      • __iter__方法需要返回对象本身,即self
      • __next__方法,返回下一个数据,如果没有数据,则需要抛出一个StopIteration异常
    #创建:迭代器类型
    class IT:
        def __init__(self):
            self.counter=0
        def __iter__(self):
            return self
        def __next__(self):
            self.counter+=1
            if self.counter==3:
                raise StopIteration()
            return self.counter
    #实例化创建一个迭代器对象
    a=IT()
    #执行方式一
    # a.__next__()
    # a.__next__()
    # a.__next__() #取值结束抛出异常StopIteration
    
    #执行方式二
    next(a) #a.__next__()
    next(a)
    next(a) #取值结束抛出异常StopIteration
    
    #执行方式三,首先会执行迭代器对象的__init__方法并获取返回值,一直反复执行(有异常则终止循环)
    # for i in a:
    #     print(a)
    
    • 生成器(其实生成器类是一种特殊的迭代器类,生成器类也是一种特殊的迭代器类)
    def func():
        yield 1
        yield 2
    #创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__,__next__方法
    a=func()
    #方式二
    # v1=next(a)
    # print(v1)
    # v2=next(a)
    # print(v2)
    # v3=next(a) #取多抛出异常StopIteration
    # print(v3)
    
    #方式一
    for i in a:
        print(i)
    
    • 可迭代对象(如果一个类中有__iter__方法且返回一个迭代器对象:称这个类创建的对象为可迭代对象)
    class Foo:
        def __iter__(self):
            return 迭代对象
    a=Foo()  #a是可迭代对象
    #可迭代对象可以使用for进行循环,在循环的内部其实是先执行__iter__方法,获取其迭代器对象,然后再内部执行这个迭代器对象的next功能,逐步取值
    for i in a:
        print(a)
    
    
    class IT(object):
        def __init__(self):
            self.counter = 0
    
        def __iter__(self):
            return self
    
        def __next__(self):
            self.counter += 1
            if self.counter == 3:
                raise StopIteration()
            return self.counter
    class Foo:
        def __iter__(self):
            return IT()
    #a为迭代器对象
    a=Foo()
    #循环可迭代对象,内部执行a.__iter__并获取迭代器对象,不断的执行迭代器对象的next方法
    for i in a:
        print(i)
    

判断是否是迭代器和迭代器对象

from collections.abc import Iterator,Iterable
v1=[11,22,33]
#判断是否是迭代器,依据:是否有__iter__,__next__
print(isinstance(v1,Iterator))  #False
v2=v1.__iter__()
print(isinstance(v2,Iterator))  #True

#判断依据;是否有__iter__且返回迭代器对象
print(isinstance(v1,Iterable))#True
print(isinstance(v2,Iterable))#True

https://www.luffycity.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

荼靡~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值