面向对象语法

私有属性

python中不存在真正意义上的私有属性,只是逻辑意义上的私有.

  • 单下划线开头属性
    定义属性和方法是私有的,不应该在类外进行访问,但是不代表无法访问.

    class A:
    	def __init__(self):
        	self._a = 11
    
    a = A()
    print(a._a)
    a._a = 22
    print(a._a)
    
    ==> 输出
    11
    22
    

    正确的访问方式应该是:将私有属性隐藏起来,暴露其他属性

    class A:
    	def __init__(self):
        	self._a = 11
    
    	@property
    	def a(self):
        	return self._a
    
    a = A()	
    print(a.a)
    ==> 输出
    11 
    
  • 双下划线开头属性

    防止子类重写父类方法
    __method方法/属性在python内部会被转化,因为两个_method不是一个方法,因此不会被重写.
    ==>
    class A中 -> _A__method
    class B中 -> _B__method

    class A(object):
    
    	def __method(self):
        	print("I'm a method in class A")
    
    	def method_x(self):
        	print("I'm another method in class A\n")
    
    	def method(self):
        	self.__method()  # 注意:此处已经被定义为_A__method,因此class B调用的时候,其实调的是_A__method
        	self.method_x()
    
    
    class B(A):
    
    	def __method(self):
        	print("I'm a method in class B")
    
    	def method_x(self):
        	print("I'm another method in class B\n")
    
    
    if __name__ == '__main__':
    	a = A()
    	a.method()
    
    	b = B()
    	b.method()
    
    	print(A.__dict__)
    	print(B.__dict__)
    
    	==> 输出
    	I'm a method in class A
    	I'm another method in class A
    
    	I'm a method in class A   # 此处没有重写父类__method方法
    	I'm another method in class B
    	
    	{'_A__method': <function A.__method at 0x0000017F875DE048>, 'method_x': <function A.method_x at 0x0000017F875DE0D0>, 'method': <function A.method at 0x0000017F875DE158>}
    	{'_B__method': <function B.__method at 0x0000017F875DE1E0>, 'method_x': <function B.method_x at 0x0000017F875DE268>}
    
  • 开头结尾下划线
    python内置方法

继承、封装、多态(接口、协议)

  • 封装

    封装行为具体实现,对外提供接口,减少了操作的复杂性.
    体现在类实例化,每个实例都拥有不同的命名空间,都是不同的对象实体.

  • 继承

    抽象共同的特征,继承父类,避免重复代码开发工作.

  • 多态
    一种事务有多种形态,比如 动物有猫、狗、猪
    重写父类的方法,实现每个实例具有不同的行为,实现多态. — 具有类型依赖关系,比如animal类的行为,被person类调用肯定不行.

    鸭子类型:
    动态语言特性:不依赖类型,取决于行为. 比如 看起来像,叫起来像鸭子的就是鸭子.
    比如:序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系.
    在比如:只要实现了__iter__和__next__方法的就是迭代器,不需要考虑继承父类实现.

  • 接口、协议
    python中接口通过抽象基类实现,定义一系列的抽象方法,通过继承在子类中实现. 抽象基类保证了一致性.

    协议:协议是非正式的接口,不施加强制性约束.
    python中有很多协议,比如迭代器协议. 得益于"鸭子类型." 多态的另一种很灵活的实现形式.

    python中使用isinstance来判断传入参数的类型是不提倡的,更pythonic的方法是直接使用传入的参数,通过try,except来处理传入参数不符合要求的情况.

property特性

如果我们直接把属性暴露出去,可能会被随意修改,不符合程序的数据类型,造成代码格式混乱.

通过property特性:

1.代码内部setter进行参数类型检测等工作.
2.简化调用,将函数调用简化为属性调用(不能传参)

class A:
	def __init__(self):
    	self._a = 11

	@property
	def a(self):
    	return self._a
    
    @a.setter
    def a(self,value):
        ...

super

  • 单继承

    单继承中 super 主要用来调用父类方法

    class A:
    	def __init__(self):
        	self.n = 2
    
    	def add(self, m):
        	print('self is {0} @A.add'.format(self))
        	self.n += m
    
    
    class B(A):
    	def __init__(self):
        	self.n = 3
    
    	def add(self, m):
        	print('self is {0} @B.add'.format(self))
        	super().add(m)
        	self.n += 3
     ==>
     b = B()
     b.add(2)
     print(b.n)
    结果:
     self is <__main__.B object at 0x106c49b38> @B.add
     self is <__main__.B object at 0x106c49b38> @A.add
     8
    
  • 多重继承
    python3中class.mro()即可查看方法解析顺序

    class A:
    	def __init__(self):
        	self.n = 2
    
    	def add(self, m):
        	print('self is {0} @A.add'.format(self))
        	self.n += m
    
    
    class B(A):
    	def __init__(self):
        	self.n = 3
    
    	def add(self, m):
        	print('self is {0} @B.add'.format(self))
        	super().add(m)
        	self.n += 3
    
    class C(A):
    	def __init__(self):
        	self.n = 4
    
    	def add(self, m):
        	print('self is {0} @C.add'.format(self))
        	super().add(m)
        	self.n += 4
    
    
    class D(B, C):
    	def __init__(self):
        	self.n = 5
    
    	def add(self, m):
        	print('self is {0} @D.add'.format(self))
        	super().add(m)
        	self.n += 5
    ==> 执行
     d = D()
     d.add(2)
     print(d.n)
    结果
     self is <__main__.D object at 0x10ce10e48> @D.add
     self is <__main__.D object at 0x10ce10e48> @B.add
     self is <__main__.D object at 0x10ce10e48> @A.add
     15
    

打包和解包

详看下面例子


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


def func1(**kwargs):
    """打包"""
    """**作用: 收集关键字参数传递给一个字典,并将这个字典赋值给变量kwargs"""
    print(kwargs)

def func2(name,age,sex):
    """解包"""
    """**作用:将k/v形式字典解包,成单独的关键字参数"""
    print(name, age, sex)

# class解包
dic = {'name':'kxc','age':25,'sex':'male'}
a = A(**dic)
print(a.__dict__)  # {'name': 'kxc', 'age': 25, 'sex': 'male'}
# def解包
func2(**dic)  # kxc 25 male
# def打包
func1(name='kxc',age=25,sex='female')  # {'name': 'kxc', 'age': 25, 'sex': 'female'}

反射机制
字符串的事件驱动模型. 利用字符串去动态导入模块、函数、实例等.

hasattr() getattr() setattr() 三个函数实现

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值