python面向对象编程(三)

本文详细探讨了Python面向对象编程的高级特性,包括成员修饰符的使用,如公有和私有成员的区别,以及特殊成员如__init__、__new__、__del__等的作用。同时,介绍了如何通过__iter__实现可迭代对象,__slots__限制类属性,__len__自定义长度,以及__getattr__处理未定义属性。

python面向对象编程(三)

  • 成员修饰符
    共有成员; 外部对象可以直接访问
    私有成员; 变量前加2下划线,默认为创建的为私有成员。无法直接访问,只能通过创建中间函数间接访问
class foo:
	sex1 = 'men1'
	__sex = 'men'
    def __init__(self,name,age):
        self.name = name
        self.__age = age

	def show(self):
		return self.__age
	
	@staticmethod
	def show2()
		return foo.__sex

obj = foo('gao','18')
print(obj.name) # gao
print(obj.__age) # 报错 AttributeError: 'foo' object has no attribute 'age'
print(obj.show()) # 18 可以已此方法访问

print(foo.sex1) # men1 静态字段同样支持此方式
print(foo.__sex1) # 报错 AttributeError: 'foo' object has no attribute '__sex1'
print(foo.show2()) # men

上代码看到,无论普通字段还是静态字段,均具有共有私有方法;
那么看看方法有没有共私有之分

class foo:
    def __fi(self):
        return 123

    def f2(self):
        r = self.__fi()
        return r

f = foo()
print(f.f2()) # 123

方法,同样有共有私有之分,当然属性也存在共私有之分,但基本上不会使用。
只有在字段与方法上,会使用成员修饰符进行共私有设置。
注意:私有不支持继承,只能自己另外创建一个共有方法间接访问父类私有

  • 特殊成员
    __init__:先前说的一个__init__构造方法就是一个特殊成员:当类加括号是,默认执行__init__
    __new__:new方法与init几乎一致,都是在创建对象时自动执行的。两者的区别是:
    a 、 __new__方法是创建对象时执行的;__init__方法是初始化对象时执行的;
    b 、 __new__方法传入第一个参数是cls即类本身,作用是将类对象本身作为模板去创建一个实列对象;__init__方法传入第一个参数是self,即已经实列的对象;
    c 、__new__方法必须要有返回值,返回值就是新建的对象;__init__方法没有返回值;
    使用__new__方法构建单例模式:

    class foo:
        _instance = None
        def __new__(cls):
            if cls._instance is None:
                cls._instance = object.__new__(cls)
            return cls._instance
    
    a = foo()
    b = foo()
    print(id(a),a) # 2192770708368 <__main__.foo object at 0x000001FE8B51B390>
    print(id(b),b) # 2192770708368 <__main__.foo object at 0x000001FE8B51B390>
    # 根据id可以看出,a、b这两个id时完全一致的,故这两个实 例实际上是一个
    
    

    __del__析构方法:构造方法时创建对象时执行的,析构方法是,对象销毁时,自动执行的,一般用不到,是python垃圾回收机构销毁对象时,自动处理了,我们无法管控。
    __call__:当类创建对象时,可以在对象后加括号,默认为执行__call__这个特殊方法

    class foo:
    	def __init__(self):
        	print('init')
    
    	def __call__(self):
        	print('call')
    
    a = foo() # init
    a() # call
    

    __int____str__:这俩种方式在对象调用int()str()函数时,会自动调用此两种方法:

    class foo:
    	def __init__(self,name):
        	self.name = name
    
    	def __int__(self):
        	return 111
    
    	def __str__(self):
        	return self.name
    
    a = foo('gao') # init
    print(a) # gao 当类中没有定义__str__特殊成员时 打印的内容为 <__main__.foo object at 0x000002887294B2E8> 
    print(str(a)) # gao
    print(int(a)) # 111
    

    __add__:两对象相加时,自动执行第一个对象的__add__方法,并将第二个对象当参数传入。执行逻辑自定义

    class foo:
    def __init__(self,n,a):
        self.name = n
        self.age = a
    
    def __add__(self, other):
        return self.age+other.age
    
    obj1 = foo('gao',21)
    obj2 = foo('qi',20)
    
    a = obj1+obj2
    print(a) # 41
    

    除了__add__加方法,还有减乘除,不多展示;

    __dict__:将对象中封装的所有内容通过字典的形式返回,或将类中的成员已字典形式返回

    class foo:
    	'''
    	注释:
    	foo 是用来测试__dict__方法返回类成员的
    	'''
    	def __init__(self,n,a):
        	self.name = n
        	self.age = a
    
    obj1 = foo('gao',21)
    obj2 = foo('qi',20)
    a = obj1.__dict__
    print(a) # {'name': 'gao', 'age': 21}
    
    print(foo.__dict__) # {'__module__': '__main__', '__doc__': '\n    \t\t注释:\n    \t\tfoo 是用来测试__dict__方法返回类成员的\n    ', '__init__': <function foo.__init__ at 0x00000133A6A800D0>, '__dict__': <attribute '__dict__' of 'foo' objects>, '__weakref__': <attribute '__weakref__' of 'foo' objects>}
    
    

    __getitem____setitem____delitem__:基于列表的方式,处理对象。

    class foo:
    	def __init__(self, n, a):
        	self.name = n
        	self.age = a
     	def __getitem__(self, item):
       	 	return item + 10
    	def __setitem__(self, key, value):
        	print('__setitem__',key, value)
    	def __delitem__(self, key):
        	print('__delitem__',key)
    
    obj1 = foo('gao', 21)
    a = obj1[10]
    print(a)  # 20
    
    obj1[2] = 'aa' # __setitem__ 2 aa
    
    del obj1[12] # __delitem__ 12
    

    在学列表对于列表处理时:除了增删改查,还有个切片处理:

    class foo:
    	def __init__(self, n, a):
        	self.name = n
       	 self.age = a
    
    	def __getitem__(self, item):
        	print(item,type(item))
        	return item,type(item)
    
    obj1 = foo('gao', 21)
    obj1[10] # 10 <class 'int'>
    obj1[1:10:2] # slice(1, 10, 2) <class 'slice'>
    
    

    可以看出,在做切片时,传入的是一个名为slice的对象,那么,在处理切片时,即可以如下处理;

    class foo:
    	def __init__(self, n, a):
        	self.name = n
       	 self.age = a
    
    	def __getitem__(self, item):
        	print(item,type(item))
        	if type(item) == slice:
            	print('调用切片处理')
            	print(item.start) # 切片开始位置
           	 	print(item.stop)  # 切片结束位置
            	print(item.step)  # 切片步长
            	'''
            	添加自己想要添加的处理方式即可
           	 	'''
        	else:
            	print('调用内部索引处理')
        	return item,type(item)
    
    obj1 = foo('gao', 21)
    obj1[10] # 10 <class 'int'> 调用内部索引处理
    obj1[1:10:2] # slice(1, 10, 2) <class 'slice'> 调用切片处理 1 10 2
    
    

    __iter__:之前学习迭代器时,有个iter()方法,可以将一个可迭代对象生成一个迭代器,现在一样,__iter__被执行后,获取的对象__iter__的返回值,循环返回值返回的对象。
    如果类中有这个方法,他创建的对象就叫做可迭代对象,
    对于可迭代对象.iter()的返回值,就是迭代器,
    对于for循环遇到迭代器,就可以直接进行next()调用
    对于foo循环遇到可迭代对象,就需要执行__iter__()先生成迭代器,在进行next()循环。

    class foo:
    	def __iter__(self):
        	return iter([11,22,33,44])
    
    a = foo()
    
    for i in a:
    	print(i) # 11 22 33 44
    

    __slots__:限制类对象属性。此限制只存在于此类中,对于他的父类或子类都不受影响

    class Foo:
        __slots__ = ('name', 'age')
    
    a = Foo()
    a.name = 'ming' # 正常向实例对象中插入属性
    a.age = 18     # 正常向实例对象中插入属性
    a.sex = 'men' # AttributeError: 'Foo' object has no attribute 'sex'
    

    __len__:可根据len()函数返回设定值:

    class Foo:
        def __len__(self):
            return 3
    
    a = Foo()
    print(len(a)) # 3
    

    __getattr__:定义一个不存在的属性,当对象调用不存在的属性时,返回对应的内容

    class Foo:
        def __init__(self):
            self.name = 'marry'
        def __getattr__(self, item):
            if item == 'sex':
                return 'women'
    
    s = Foo()
    print(s.name) # marry  存在name属性,取值
    print(s.sex)  # women  使用__getattr__特殊方法返回属性 注意只有当内容中不存在想要调用的属性时,才会执行__getattr__方法,存在会返回原属性内容
    print(s.age)  # None   不存在此属性,默认返回None 可以通过raise自定义一个属性不存在报错
    

    __instance:创建单列模式;何为创建单列模式,正常的类,每次实例化都会创建一个实例化对象,如果存在__onstance这个私有变量是,该类实列化时,不会创建新的对象,而会将已经创建的实列对象返回,故称之为:单列模式。

    class Foo:
    	__instance = None
        def __new__(cls,name,age):
        	# 如果类属性__instance 的值为None 就会创建一个对象,并赋值为这个对象引用,保证下次调用这个方法时,能够知道已经创建对象了,这样就保证了,永远都只存在一个对象
            if not cls.__instance:
            	cls.__instance = object.__new__(cls)
            return cls.__instance
    
    s = Foo('gao',23)
    s2 = Foo('cao',21)
    # 打印出两个对象的id可知,地址完全一致,是一个对象
    print(id(s))
    print(id(s1))
    
    s.age = 19 # 给a对象属性赋值
    print(s2.age) # 19
    
    

    __doc__:编写改类的说明文档,可通过help()函数调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值