Python系统学习-06

xiaoxiao2021-02-28  42

1.递归函数

自己调用自己一般递归100多次,没有解决问题就不要用了

1.1用递归解决年龄问题

def age(n): if n == 1: #终止条件 return 23 else: return age(n-1)+2 #通相式 print(age(4))

1.2二分查找

前提条件:列表必须是有序的不重复数字列表

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))

2.面向对象

实际工作中,python都是面向对象,写代码,或者面向对象+函数。

2.1面向对象编程:上帝式思维

class Person: #class关键字,定义了一个类 ''' 类里面所有内容 ''' animal = '高级动物' #静态变量 soup = '有思想' def __init__(self,name,eye): self.name = name #属性 self.eye = eye print(666) def work(self): #动态变量,方法 print('工作。。。。')

2.2什么是类?

“类”是具有相同属性和技能的一类事物“对象”实例化的一个类,是类的具体体现类如何调用查看静态变量,动态变量\特殊的类属性 类名.name# 类的名字(字符串) 类名.doc# 类的文档字符串 类名.base# 类的第一个父类(在讲继承时会讲) 类名.bases# 类所有父类构成的元组(在讲继承时会讲) 类名.dict# 类的字典属性 类名.module# 类定义所在的模块 类名.class# 实例对应的类(仅新式类中)

2.2.1类操作静态变量有两种方式:

1.类名.dict方法

print(Person.__dict__) #打印所有静态变量,只能查看,不能增加,修改,删除 print(Person.__dict__['animal'])

2.类名.变量名

print(Person.animal) Person.animal = '低等动物' #可以增,删,改,查

2.2.2类操作方法有两种方式:

1类名.dict[方法名]()

print(Person.__dict__['work']())

3.2类名.方法名

Person.work(11)

2.3对象

类名() #实例化一个对象 p1 = Persion() #p1对象,实例化对象,类名()过程就叫做实例化。 p2 = Person()

只要创建一个类,里面的内容就已经加载到内存。 p1 = Person() #init叫构造方法,创建对象时候自动调用。 内部进行三步: 1.实例化一个对象,在内存中产生一个对象空间。> 2.自动执行init方法,并将这个空间对象传给self> 3.通过构造方法里的代码给空间添加一些属性,并返回给对象。

2.4对象操作属性:

1.print(p1.dict) 2.对象.变量名 print(p1.name) 3.增删改查 p1.color = red print(p1.color)

2.5对象操作方法有2种:

p1 = Person(‘Morgan’,’big’) 1. 对象.方法名()

p1.work() print(p1)

2.类名.方法名(对象)

Person.work(111)

3.对象可以访问类的静态变量

print(p1.animal)

通过实例化对象查找属性,先从对象空间找,没有则通过类对象指针从类空间找。

3.组合

就是让不同的类混合并加入到其他类中,来增强功能和代码重用性

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)

3.1面向对象三大特点

3.1.1封装

隐藏对象的属性和实现细节,仅对外提供公共访问方式。 【好处】 1. 将变化隔离; 2. 便于使用; 3. 提高复用性; 4. 提高安全性; 【封装原则】 1. 将不需要对外提供的内容都隐藏起来; 2. 把属性都隐藏,提供公共方法对其访问。

3.1.1.1私有变量和私有方法

私有变量

在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

3.1.2继承

可以有效节省代码。python3中,所有的类都默认继承object类,继承object类的类称为新式类。python中,类分为两种:新式类,经典类。但是python3中只有新式类,python2中都有。新式类继承顺序:遵循广度优先(是一个算法,每个节点只走一次,用最少的次数。)经典类继承顺序:遵循深度优先

3.1.2.1继承:单继承,多继承。

重写父类方法

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) 接口回去看

3.3多态

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,这些继承关系看上去就像一颗倒着的树。

3.4抽象类与接口类

继承有两种用途:

继承基类的方法,并且做出自己的改变或者扩展(代码重用) 声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

3.4.1接口继承

继承的第二种含义非常重要。它又叫“接口继承”。

借用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(): pass

4.call内置函数的作用和用法

Python中,一个特殊的魔术方法可以让类的实例的行为表现的像函数一样,你可以调用他们,将一个函数当做一个参数传到另外一个函数中等等。这是一个非常强大的特性让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)
转载请注明原文地址: https://www.6miu.com/read-2626755.html

最新回复(0)