前提条件:列表必须是有序的不重复数字列表
l = [1,2,3,4,5] def search(l, target,start=0,end=len(l)-1): if end >= start: mid_index = end-start // 2 + start if target > l[mid_index]: return search(l,target,start=mid_index+1,end=len(l)-1) elif target < l[mid_index]: return search(l,target,start=0,end=mid_index-1) elif target == l[mid_index]: return mid_index else: return 'no this value' else: return 'no this value' print(search(l,3))实际工作中,python都是面向对象,写代码,或者面向对象+函数。
1.类名.dict方法
print(Person.__dict__) #打印所有静态变量,只能查看,不能增加,修改,删除 print(Person.__dict__['animal'])2.类名.变量名
print(Person.animal) Person.animal = '低等动物' #可以增,删,改,查1类名.dict[方法名]()
print(Person.__dict__['work']())3.2类名.方法名
Person.work(11)类名() #实例化一个对象 p1 = Persion() #p1对象,实例化对象,类名()过程就叫做实例化。 p2 = Person()
只要创建一个类,里面的内容就已经加载到内存。 p1 = Person() #init叫构造方法,创建对象时候自动调用。 内部进行三步: 1.实例化一个对象,在内存中产生一个对象空间。> 2.自动执行init方法,并将这个空间对象传给self> 3.通过构造方法里的代码给空间添加一些属性,并返回给对象。
1.print(p1.dict) 2.对象.变量名 print(p1.name) 3.增删改查 p1.color = red print(p1.color)
p1 = Person(‘Morgan’,’big’) 1. 对象.方法名()
p1.work() print(p1)2.类名.方法名(对象)
Person.work(111)3.对象可以访问类的静态变量
print(p1.animal)通过实例化对象查找属性,先从对象空间找,没有则通过类对象指针从类空间找。
就是让不同的类混合并加入到其他类中,来增强功能和代码重用性
class Game_person: def __init__(self,nickname,sex,hp,ad): self.nickname = nickname self.sex = sex self.hp = hp self.ad = ad def attack(self,p): p.hp -= self.ad print('%s攻击了%s,%s还剩%s血量'%(self.nickname,p.nickname,p.nickname,p.hp)) def weapon_attack(self,武器): self.武器 = 武器 #斧子对象 class Weapon: def __init__(self,name,ad): self.name=name self.ad=ad def fight(self,p1,p2): p2.hp -= self.ad print('%s使用%s打了%s%s血,%s还剩%s滴血'\ %(p1.nickname,self.name,p2.nickname,self.ad,p2.nickname,p2.hp)) ts = Game_person('泰森','男',200,50) barry = Game_person('太白','男',100,10) fuzi = Weapon('斧子',60) barry.weapon_attack(fuzi) barry.武器.fight(barry,ts)隐藏对象的属性和实现细节,仅对外提供公共访问方式。 【好处】 1. 将变化隔离; 2. 便于使用; 3. 提高复用性; 4. 提高安全性; 【封装原则】 1. 将不需要对外提供的内容都隐藏起来; 2. 把属性都隐藏,提供公共方法对其访问。
私有变量
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)类中所有双下划线开头的名称如_x都会自动变形成:类名__x的形式: class A: __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N def __init__(self): self.__X=10 #变形为self._A__X def __foo(self): #私有函数,变形为_A__foo print('from A') def bar(self): self.__foo() #只有在类内部才可以通过__foo的形式访问到. #A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形这种自动变形的特点: 1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。 2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。 3.在子类定义的_x不会覆盖在父类定义的__x,因为子类中变形成了:子类名_x,而父类中变形成了:父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
私有方法
在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的,例如以下: class A: def fa(self): print('from A') def test(self): self.fa() class B(A): def fa(self): print('from B') b = B() b.test() #输出:from B ==================================== #把fa定义成私有的,即__fa ==================================== class A: def __fa(self): print('from A') def test(self): self.__fa() class B(A): def __fa(self): print('from B') b = B() b.test() #输出:from A重写父类方法
super().init
class FooParent: def __init__(self): self.parent = 'I \'m the parent.' print('Parent') def bar(self, message): print("%s from parent" % message) class FooChild(FooParent): def __init__(self): super(FooChild, self).__init__() print('child') def bar(self, message): super(FooChild, self).bar(message) print('child bar function') print(self.parent) if __name__ == '__main__': fooChild = FooChild() fooChild.bar('helloworld') 输出: Parent child helloworld from parent child bar function I 'm the parent.单继承:一个一个往上找。 多继承:先平级找,然后再下级中找。 Tips 类名.mro()查询继承顺序
经典类:深度优先 python2默认经典类,如果改成新式类就让类继承(object) 接口回去看
Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。
class Animal: def run(self): print('Animal is running...') class Dog(Animal): def run(self): print('Dog is running...') class Cat(Animal): pass class Tortoise(Animal): #你会发现,新增一个Animal的子类,不必对run_twice()做任何修改,实际上, # 任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。 def run(self): print('Tortoise is running slowly...') def run_twice(animal): animal.run() animal.run() dog = Dog() cat = Cat() run_twice(Tortoise())多态的好处就是,当我们需要传入Dog、Cat、Tortoise……时,我们只需要接收Animal类型就可以了,因为Dog、Cat、Tortoise……都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思: 对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,而具体调用的run()方法是作用在Animal、Dog、Cat还是Tortoise对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则: 对扩展开放:允许新增Animal子类; 对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。 继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树。
继承有两种用途:
继承基类的方法,并且做出自己的改变或者扩展(代码重用) 声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能继承的第二种含义非常重要。它又叫“接口继承”。
借用abc模块来实现接口
class Payment(metaclass=ABCMeta): @abstractmethod def pay(self,money): pass class Wechatpay(Payment): def fuqian(self,money): print('微信支付了%s元'%money) p = Wechatpay() #TypeError: Can't instantiate abstract class Wechatpay with abstract methods pay ============================================================= from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, maxbytes=-1): print('read1') @abstractmethod def write(self, data): print('write1') class SocketStream(IStream): def read(self, maxbytes=-1): return 'read' def write(self, data): return 'write' p = SocketStream() print(p.read()) #输出:read上面例子详细说明: @abstractmethod 还能注解静态方法、类方法和 properties 。 你只需保证这个注解紧靠在函数定义前即可:
class A(metaclass=ABCMeta): @property @abstractmethod def name(self): pass @name.setter @abstractmethod def name(self, value): pass @classmethod @abstractmethod def method1(cls): pass @staticmethod @abstractmethod def method2(): passPython中,一个特殊的魔术方法可以让类的实例的行为表现的像函数一样,你可以调用他们,将一个函数当做一个参数传到另外一个函数中等等。这是一个非常强大的特性让Python编程更加舒适甜美。 call(self, [args…])
class X(object): def __init__(self, a, b, range): self.a = a self.b = b self.range = range def __call__(self, a, b): self.a = a self.b = b print('__call__ with ({}, {})'.format(self.a, self.b)) def __del__(self, a, b, range): del self.a del self.b del self.range >>> xInstance = X(1, 2, 3) >>> xInstance(1,2) __call__ with (1, 2)