继承的重点 1、子类拥有父类 非私有化的属性和方法。
2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
3、子类可以用自己的方式实现父类的方法。(重写)。
单继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Animal : def eat (self ): print ("eating..." ) def sleep (self ): print ("sleep..." ) // 继承父类的方法 class Dog (Animal ): def swimming (self ): print ("goupaoshi..." ) class Cat (Animal ): def climb_tree (self ): print ("climb_tree..." ) alex = Dog() alex.eat()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Animal : def eat (self ): print ('eating ...' ) def sleep (self ): print ('sleeping ...' ) // 重写父类方法 class Dog (Animal ): def swimming (self ): print ('狗刨式...' ) def sleep (self ): print ('趴着睡' ) alex = Dog() alex.sleep()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Animal : def eat (self ): print ('eating ...' ) def sleep (self ): print ('sleeping ...' ) // 调用父类的方法 class Dog (Animal ): def swimming (self ): print ('狗刨式...' ) def sleep (self ): super ().sleep() print ('趴着睡' ) alex = Dog() alex.sleep() class Person (object ): def __init__ (self, name, age ): self .name = name self .age = age def sleep (self ): print ("基类sleep..." ) class TL (Person ): def __init__ (self, name, age, dep ): super ().__init__(name, age) self .dep = dep yuan = TL("yuan" , 18 , "游戏部" ) yuan.sleep() print (yuan.dep)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class A : x = 100 def __int__ (self, x ): self .x = x def foo (self ): print (self .x) class B (A ): x = 12 b = B() b.foo() // 12
demo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 import randomimport datetimeprint (''' 1、海尔冰箱 单价3000元; 2、西门子洗衣机 单价5000元; 3、芝华士沙发 单价6000元 ''' )goods = {1 : ("海尔冰箱" , 3000 ), 2 : ("西门子洗衣机" , 5000 ), 3 : ("芝华士沙发" , 6000 )} class Bill (object ): def __init__ (self,name ): self .name=name def get_unit (self ): unit = int (input ("请输入商品序号>>>" )) return unit def get_number (self ): number = int (input ("请输入商品数量>>>" )) return number def get_total_price (self ): unit = self .get_unit() number = self .get_number() total_price = goods[unit][1 ] * number ret = self .discount(total_price) print ("%s于%s总共花费%s元" %(self .name,datetime.datetime.today(),ret)) return ret def discount (self,price ): return price class NationalDayBill (Bill ): def discount (self, price ): if price > 399 : return price-200 return super ().discount(price) class Double11Bill (Bill ): def discount (self,price ): if price > 200 : free = random.randint(0 , 1 ) if free == 0 : return 0 return super ().discount(price) class MiddleAutumeBill (NationalDayBill ): def discount (self, price ): if price > 500 : temp_price = super ().discount(price) return temp_price*0.8 return super ().discount(price) mab=MiddleAutumeBill("Yuan" ) mab.get_total_price()
多继承 继承中查找方法的方法顺序是:先查子类,然后从左往右,从最左边父类找,没有的话再往右边的类找,可以使用__mro__查看
查看实例的所有属性:dir()方法和__dict__属性 dir(obj)可以获得对象的所有属性列表, 而obj.__dict__对象的自定义属性字典
判断类的继承关系:type 和isinstance方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Animal : def eat (self ): print ("eating..." ) def sleep (self ): print ("sleep..." ) class Dog (Animal ): def swim (self ): print ("swimming..." ) alex = Dog() mjj = Dog() a = Animal() print (isinstance (alex, Dog)) print (isinstance (alex, Animal)) print (type (alex)) print (isinstance (a, Dog)) print (issubclass (Animal, (Dog,))) print (issubclass (Dog, (Animal,)))
封装好处
隐藏实现细节,提供公共的访问方式
提高了代码的复用性
提高安全性
私有属性
私有属性 只能在 本类 使用
确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。
这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名 和属性名 就可以拼出名字:
_类名__属性, 然后就可以访问了,如 alex._Student__score
单下划线、双下划线、头尾双下划线说明foo : 定义的是特殊方法,一般是系统定义名字 ,类似 init () 之类的。
_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问。(约定成俗,不限语法)
__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。
多态 多态是指一类事物有多种形态。比如动物有多种形态,人,狗,猫,等等。文件有多种形态:文本文件,可执行文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 from abc import ABCMeta, abstractmethod class Payment (metaclass=ABCMeta): def __init__ (self, name, money ): self .money = money self .name = name @abstractmethod def pay (self, *args, **kwargs ): pass class AliPay (Payment ): def pay (self ): print ('%s通过支付宝消费了%s元' % (self .name, self .money)) class WeChatPay (Payment ): def pay (self ): print ('%s通过微信消费了%s元' % (self .name, self .money)) class Order (object ): def account (self, pay_obj ): pay_obj.pay() pay_obj = WeChatPay("yuan" , 100 ) pay_obj2 = AliPay("alex" , 200 ) order = Order() order.account(pay_obj) order.account(pay_obj2)
在上面的例子中order.account(pay_obj)中pay_obj不需要类型声明,而java在使用时要定义好类型
(order.account(Payment pay_obj)),所以你传入别的类型对象一定报错
但是python因为是动态语言所以传入的对象只要拥有调用的方法即可视为Payment类型对象,这就是所谓的鸭子类型
鸭子模型 鸭子类型(英語:duck typing)在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由「当前方法和属性的集合」决定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Duck : def quack (self ): print ("这鸭子正在嘎嘎叫" ) def feathers (self ): print ("这鸭子拥有白色和灰色的羽毛" ) class Person : def quack (self ): print ("这人正在模仿鸭子" ) def feathers (self ): print ("这人在地上拿起1根羽毛然后给其他人看" ) def in_the_forest (duck ): duck.quack() duck.feathers() def game (): donald = Duck() john = Person() in_the_forest(donald) in_the_forest(john) game() from collections.abc import Iterableclass Company : def __init__ (self, employee_list ): self .employee = employee_list def __iter__ (self ): return iter (self .employee) def __getitem__ (self, item ): return self .employee[item] if __name__ == "__main__" : company = Company(["tom" , "bob" , "jane" ]) if isinstance (company, Iterable): print ("company是iterable类型" ) for item in company: print (item) a = [] if isinstance (a, Iterable): print ("yes" )
反射 指程序可以访问、检测和修改它本身状态或行为的一种能力,在python中一切皆对象(类,实例,模块等等都是对象),那么我们就可以通过反射的形式操作对象相关的属性。
闭包 当一个变量既不是该函数内部的局部变量,也不是该函数的参数,相对于作用域来说,就是一个自由变量(引用了外部变量),这样就会形成一个闭包。
上下文管理器 1 2 3 4 5 6 7 8 9 10 11 12 class Resource (): def __enter__ (self ): print ('===connect to resource===' ) return self def __exit__ (self, exc_type, exc_val, exc_tb ): print ('===close resource connection===' ) def operate (self ): print ('===in operation===' ) with Resource() as res: res.operate()
异常可以在__exit__ 进行捕获并由你自己决定如何处理,是抛出呢还是在这里就解决了。在__exit__ 里返回 True(没有return 就默认为 return False),就相当于告诉 Python解释器,这个异常我们已经捕获了,不需要再往外抛了。
在 写__exit__ 函数时,需要注意的事,它必须要有这三个参数:
exc_type:异常类型
exc_val:异常值
exc_tb:异常的错误栈信息
当主逻辑代码没有报异常时,这三个参数将都为None。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import contextlib@contextlib.contextmanager def open_func (file_name ): print ('open file:' , file_name, 'in __enter__' ) file_handler = open (file_name, 'r' ) try : yield file_handler except Exception as exc: print ('the exception was thrown' ) finally : print ('close file:' , file_name, 'in __exit__' ) file_handler.close() return with open_func('/Users/MING/mytest.txt' ) as file_in: for line in file_in: 1 /0 print (line)
在被装饰函数里,必须是一个生成器(带有yield),而yield之前的代码,就相当于__enter__里的内容。yield 之后的代码,就相当于__exit__ 里的内容。
作用域链
L (Local) 局部作用域(一般指函数,在函数内部定义的则是局部变量)
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
搜索作用域 1.python 先从局部作用域开始搜索,没找到则在全局域继续搜索,否则就会抛出 NameError 异常;
2.全局变量能被同名的局部变量所覆盖;
3.变量的作用域受到命名空间的影响。
访问规则
访问规则链:L => E => G => B
从 局部作用域 开始查找,如果 局部作用域 不存在,则往上一层(也就是指嵌套函数)开始查找,如果上一层也不存在,则继续向上,一直到(这个过程都是与
闭包函数外的函数全局作用域,如果全局作用于也不存在,则在 内建作用域 查找,如果依然不存在,则报错 is not defined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 x=10 def outer (): y=20 ; print (x) def inner (): z=30 print (f"x={x} ,y={y} " ) inner() outer() c = 1 def func1 (): c = 2 def func2 (): c = 3 print (c) func2() func1()
内部修改外部变量 1 2 3 4 5 6 7 8 9 10 11 x=10 def changeNum (): x=20 print (x) changeNum() print (x)
1 2 3 4 5 6 7 8 9 10 11 12 x=10 def changeNum (): print (x) x=20 print (x) changeNum()
如果,修改一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 x=10 def changeNum (): def changeMore (): print (x) x=20 print (x) changeMore() changeNum() ''' 20 20 ''' x=10 def changeNum (): def changeMore (): print (x) changeMore() x=20 print (x) changeNum()
如果同样的代码换成js了
1 2 3 4 5 6 7 8 9 10 11 12 13 var a = 10 function xx ( ){ function x ( ){ console .log (a) } x () a = 20 console .log (a) } xx ()
摘录:https://blog.csdn.net/Sunny_Future/article/details/114757132