阿里天池Python训练营task03

一、函数

1. 函数的定义

还记得 Python 里面“万物皆对象”么?Python 把函数也当成对象,可以从另一个函数中返回出来而去构建高阶函数,比如: 参数是函数、返回值是函数。

我们首先来介绍函数的定义。

  • 函数以def关键词开头,后接函数名和圆括号()。
  • 函数执行的代码以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None。
def functionname (parameters):"函数_文档字符串"function_suitereturn [expression]

2.函数的调用

def printme(str):print(str)printme("我要调用用户自定义函数!")  # 我要调用用户自定义函数!
printme("再次调用同一函数")  # 再次调用同一函数
temp = printme('hello') # hello
print(temp)  # None
print('===================')
printme('hello')# hello

3.函数文档

def MyFirstFunction(name):"函数定义过程中name是形参"# 因为Ta只是一个形式,表示占据一个参数位置print('传递进来的{0}叫做实参,因为Ta是具体的参数值!'.format(name))MyFirstFunction('老马的程序人生')
# 传递进来的老马的程序人生叫做实参,因为Ta是具体的参数值!print(MyFirstFunction.__doc__)
# 函数定义过程中name是形参help(MyFirstFunction)
# Help on function MyFirstFunction in module __main__:
# MyFirstFunction(name)
#    函数定义过程中name是形参

4.函数参数

Python 的函数具有非常灵活多样的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。从简到繁的参数形态如下:

  • 位置参数 (positional argument)
  • 默认参数 (default argument)
  • 可变参数 (variable argument)
  • 关键字参数 (keyword argument)
  • 命名关键字参数 (name keyword argument)
  • 参数组合

1.位置参数

def functionname(arg1):"函数_文档字符串"function_suitereturn [expression]
  • agr1 --位置参数,这些参数在调用函数(call function )时位置要固定

2.默认参数

def functionname(arg1, arg2=v):"函数_文档字符串"function_suitereturn [expression]
  • arg2 = v - 默认参数 = 默认值,调用函数时,默认参数的值如果没有传入,则被认为是默认值。
  • 默认参数一定要放在位置参数 后面,不然程序会报错。
def printinfo(name, age=8):print('Name:{0},Age:{1}'.format(name, age))printinfo('小马')  # Name:小马,Age:8
printinfo('小马', 10)  # Name:小马,Age:10
  • Python 允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
def printinfo(name, age):print('Name:{0},Age:{1}'.format(name, age))printinfo(age=8, name='小马')  # Name:小马,Age:8

3.可变参数

顾名思义,可变参数就是传入的参数个数是可变的,可以是 0, 1, 2 到任意个,是不定长的参数。

def functionname(arg1, arg2=v, *args):"函数_文档字符串"function_suitereturn [expression]
  • *args - 可变参数,可以是从零个到任意个,自动组装成元组。
  • 加了星号(*)的变量名会存放所有未命名的变量参数。
def printinfo(arg1, *args):print(arg1)for var in args:print(var)printinfo(10)  # 10
printinfo(70, 60, 50)
# 70
# 60
# 50

4.关键字参数

def functionname(arg1, arg2=v, args, *kw):"函数_文档字符串"function_suitereturn [expression]
  • **kw - 关键字参数,可以是从零个到任意个,自动组装成字典。
def printinfo(arg1, *args, **kwargs):print(arg1)print(args)print(kwargs)printinfo(70, 60, 50)
# 70
# (60, 50)
# {}
printinfo(70, 60, 50, a=1, b=2)
# 70
# (60, 50)
# {'a': 1, 'b': 2}

「可变参数」和「关键字参数」的同异总结如下:

  • 1.可变参数允许传入零个到任意个参数,它们在函数调用时自动组装为一个元组 (tuple)。
  • 2.关键字参数允许传入零个到任意个参数,它们在函数内部自动组装为一个字典 (dict)。

5.命名关键字参数

def functionname(arg1, arg2=v, *args, *, nkw, **kw):"函数_文档字符串"function_suitereturn [expression]
  • *, nkw - 命名关键字参数,用户想要输入的关键字参数,定义方式是在nkw 前面加个分隔符 *。
  • 如果要限制关键字参数的名字,就可以用「命名关键字参数」
  • 使用命名关键字参数时,要特别注意不能缺少参数名。
def printinfo(arg1, *, nkw, **kwargs):print(arg1)print(nkw)print(kwargs)
printinfo(70, nkw=10, a=1, b=2)
# 70
# 10
# {'a': 1, 'b': 2}
printinfo(70, 10, a=1, b=2)
# TypeError: printinfo() takes 1 positional argument but 2 were given
  • 没有写参数名 nwk ,因此 10 被当成「位置参数」,而原函数只有 1 个位置函数,现在调用了 2 个,因此程序会报
    错。

6.参数组合

在 Python 中定义函数,可以用位置参数、默认参数、可变参数、命名关键字参数和关键字参数,这 5 种参数中的 4 个都
可以一起使用,但是注意,参数定义的顺序必须是:

  • 位置参数、默认参数、可变参数和关键字参数。
  • 位置参数、默认参数、命名关键字参数和关键字参数。

要注意定义可变参数和关键字参数的语法:

  • *args 是可变参数, args 接收的是一个 tuple
  • **kw 是关键字参数, kw 接收的是一个 dict

命名关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。定义命名关键字参数不要忘了写分隔符 * ,否则定义的是位置参数。

警告:虽然可以组合多达 5 种参数,但不要同时使用太多的组合,否则函数很难懂。

5.函数的返回值

6.变量的作用域

1.局部变类和全局变量

  • Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
  • 定义在函数内部的变量拥有局部作用域,该变量称为局部变量。
  • 定义在函数外部的变量拥有全局作用域,该变量称为全局变量。
  • 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问
def discounts(price, rate):final_price = price * ratereturn final_priceold_price = float(input('请输入原价:'))  # 98
rate = float(input('请输入折扣率:'))  # 0.9
new_price = discounts(old_price, rate)
print('打折后价格是:%.2f' % new_price)  # 88.20
  • 当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了。
num = 1def fun1():global num  # 需要使用 global 关键字声明print(num)  # 1num = 123print(num)  # 123fun1()
print(num)  # 123

2.闭包

  • 是函数式编程的一个重要的语法结构,是一种特殊的内嵌函数。
  • 如果在一个内部函数里对外层非全局作用域的变量进行引用,那么内部函数就被认为是闭包。
  • 通过闭包可以访问外层非全局作用域的变量,这个作用域称为 闭包作用域。
def funX(x):def funY(y):return x * yreturn funYi = funX(8)
print(type(i))  # <class 'function'>
print(i(5))  # 40
def outer():num = 10def inner():nonlocal num  # nonlocal关键字声明num = 100print(num)inner()print(num)
outer()

3.递归

  • 如果一个函数在内部调用自身本身,这个函数就是递归函数
def recur_fibo(n):if n <= 1:return nreturn recur_fibo(n - 1) + recur_fibo(n - 2)
n=12
lst=list()
for k in range(n):lst.append(recur_fibo(k))
print(lst)

设置递归的层数,Python默认递归层数为 100

import syssys.setrecursionlimit(1000)

二、 lanmbda表达式

1.匿名函数的定义

在 Python 里有两类函数:

  • 第一类:用 def 关键词定义的正规函数
  • 第二类:用 lambda 关键词定义的匿名函数
    Python 使用 lambda 关键词来创建匿名函数,而非def关键词,它没有函数名,其语法结构如下:
lambda argument_list: expression
  • lambda - 定义匿名函数的关键词。
  • argument_list - 函数参数,它们可以是位置参数、默认参数、关键字参数,和正规函数里的参数类型一样。
  • :- 冒号,在函数参数和表达式中间要加个冒号。
  • expression - 只是一个表达式,输入函数参数,输出一些值。

注意:

  • expression 中没有 return 语句,因为 lambda 不需要它来返回,表达式本身结果就是返回值。
  • 匿名函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
def sqr(x):return x ** 2print(sqr)
# <function sqr at 0x000000BABD3A4400>y = [sqr(x) for x in range(10)]
print(y)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]lbd_sqr = lambda x: x ** 2
print(lbd_sqr)
# <function <lambda> at 0x000000BABB6AC1E0>y = [lbd_sqr(x) for x in range(10)]
print(y)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]sumary = lambda arg1, arg2: arg1 + arg2
print(sumary(10, 20))  # 30func = lambda *args: sum(args)
print(func(1, 2, 3, 4, 5))  # 15

2.匿名函数的应用

函数式编程 是指代码中每一块都是不可变的,都由纯函数的形式组成。这里的纯函数,是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出,没有任何副作用。
非函数式编程

def f(x):for i in range(0, len(x)):x[i] += 10return xx = [1, 2, 3]
f(x)
print(x)
# [11, 12, 13]

函数式编程

def f(x):y = []for item in x:y.append(item + 10)return yx = [1, 2, 3]
f(x)
print(x)
# [1, 2, 3]

匿名函数 常常应用于函数式编程的高阶函数 (high-order function)中,主要有两种形式:

  • 参数是函数 (filter, map)
  • 返回值是函数 (closure)
    如,在 filter和map函数中的应用:
  • filter(function, iterable) 过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。
odd = lambda x: x % 2 == 1
templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(templist))  # [1, 3, 5, 7, 9]
  • map(function, *iterables) 根据提供的函数对指定序列做映射.
m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(list(m1))
# [1, 4, 9, 16, 25]m2 = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
print(list(m2))
# [3, 7, 11, 15, 19]

除了 Python 这些内置函数,我们也可以自己定义高阶函数

def apply_to_list(fun, some_list):return fun(some_list)lst = [1, 2, 3, 4, 5]
print(apply_to_list(sum, lst))
# 15print(apply_to_list(len, lst))
# 5print(apply_to_list(lambda x: sum(x) / len(x), lst))

三、类与对象

1.对象=属性+方法

对象是类的实例。换句话说,类主要定义对象的结构,然后我们以类为模板创建对象。类不但包含方法定义,而且还包含所有实例共享的数据。

  • 封装:信息隐蔽技术

我们可以使用关键字 class 定义 Python 类,关键字后面紧跟类的名称、分号和类的实现。

class Turtle:  # Python中的类名约定以大写字母开头"""关于类的一个简单例子"""# 属性color = 'green'weight = 10legs = 4shell = Truemouth = '大嘴'# 方法def climb(self):print('我正在很努力的向前爬...')def run(self):print('我正在飞快的向前跑...')def bite(self):print('咬死你咬死你!!')def eat(self):print('有得吃,真满足...')def sleep(self):print('困了,睡了,晚安,zzz')tt = Turtle()
print(tt)
# <__main__.Turtle object at 0x0000007C32D67F98>print(type(tt))
# <class '__main__.Turtle'>print(tt.__class__)
# <class '__main__.Turtle'>print(tt.__class__.__name__)
# Turtlett.climb()
# 我正在很努力的向前爬...tt.run()
# 我正在飞快的向前跑...tt.bite()
# 咬死你咬死你!!# Python类也是对象。它们是type的实例
print(type(Turtle))
# <class 'type'>
  • 继承:子类自动共享父类之间数据和方法的机
class MyList(list):passlst = MyList([1, 5, 2, 7, 8])
lst.append(9)
lst.sort()
print(lst)# [1, 2, 5, 7, 8, 9]
  • 多态:不同对象对同一方法响应不同的行动
class Animal:def run(self):raise AttributeError('子类必须实现这个方法')class People(Animal):def run(self):print('人正在走')class Pig(Animal):def run(self):print('pig is walking')class Dog(Animal):def run(self):print('dog is running')def func(animal):animal.run()func(Pig())
# pig is walking

2.self是什么?

Python 的 self 相当于 C++ 的 this 指针。

class Test:def prt(self):print(self)print(self.__class__)t = Test()
t.prt()
# <__main__.Test object at 0x000000BC5A351208>

类的方法与普通的函数只有一个特别的区别 —— 它们必须有一个额外的第一个参数名称(对应于该实例,即该对象本身),按照惯例它的名称是 self。在调用方法时,我们无需明确提供与参数 self 相对应的参数

class Ball:def setName(self, name):self.name = namedef kick(self):print("我叫%s,该死的,谁踢我..." % self.name)a = Ball()
a.setName("球A")
b = Ball()
b.setName("球B")
c = Ball()
c.setName("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...

3.Python的魔法方法

据说,Python 的对象天生拥有一些神奇的方法,它们是面向对象的 Python 的一切…
它们是可以给你的类增加魔力的特殊方法…
如果你的对象实现了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,而这一切都是自动发生的…
类有一个名为__init__(self[, param1, param2…])的魔法方法,该方法在类实例化时会自动调用。

class Ball:def __init__(self, name):self.name = namedef kick(self):print("我叫%s,该死的,谁踢我..." % self.name)a = Ball("球A")
b = Ball("球B")
c = Ball("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...

4.公有和私有

在 Python 中定义私有变量只需要在变量名或函数名前加上“__”两个下划线,那么这个函数或变量就会为私有的了
类的私有属性实例

class JustCounter:__secretCount = 0  # 私有变量publicCount = 0  # 公开变量def count(self):self.__secretCount += 1self.publicCount += 1print(self.__secretCount)counter = JustCounter()
counter.count()  # 1
counter.count()  # 2
print(counter.publicCount)  # 2# Python的私有为伪私有
print(counter._JustCounter__secretCount)  # 2
print(counter.__secretCount)
# AttributeError: 'JustCounter' object has no attribute '__secretCount'

类的私有方法实例

class Site:def __init__(self, name, url):self.name = name  # publicself.__url = url  # privatedef who(self):print('name  : ', self.name)print('url : ', self.__url)def __foo(self):  # 私有方法print('这是私有方法')def foo(self):  # 公共方法print('这是公共方法')self.__foo()x = Site('老马的程序人生', 'https://blog.csdn.net/LSGO_MYP')
x.who()
# name  :  老马的程序人生
# url :  https://blog.csdn.net/LSGO_MYPx.foo()
# 这是公共方法
# 这是私有方法x.__foo()
# AttributeError: 'Site' object has no attribute '__foo'

5.继承

Python 同样支持类的继承,派生类的定义如下所示:

class DerivedClassName(BaseClassName):statement-1...statement-N

BaseClassName(基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:

class DerivedClassName(modname.BaseClassName):statement-1...statement-N

如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。

# 类定义
class people:# 定义基本属性name = ''age = 0# 定义私有属性,私有属性在类外部无法直接进行访问__weight = 0# 定义构造方法def __init__(self, n, a, w):self.name = nself.age = aself.__weight = wdef speak(self):print("%s 说: 我 %d 岁。" % (self.name, self.age))# 单继承示例
class student(people):grade = ''def __init__(self, n, a, w, g):# 调用父类的构函people.__init__(self, n, a, w)self.grade = g# 覆写父类的方法def speak(self):print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))s = student('小马的程序人生', 10, 60, 3)
s.speak()
# 小马的程序人生 说: 我 10 岁了,我在读 3 年级

注意:如果上面的程序去掉:people.init(self, n, a, w),则输出:说: 我 0 岁了,我在读 3 年级,因为子类的构造方法把父类的构造方法覆盖了

import randomclass Fish:def __init__(self):self.x = random.randint(0, 10)self.y = random.randint(0, 10)def move(self):self.x -= 1print("我的位置", self.x, self.y)class GoldFish(Fish):  # 金鱼passclass Carp(Fish):  # 鲤鱼passclass Salmon(Fish):  # 三文鱼passclass Shark(Fish):  # 鲨鱼def __init__(self):self.hungry = Truedef eat(self):if self.hungry:print("吃货的梦想就是天天有得吃!")self.hungry = Falseelse:print("太撑了,吃不下了!")self.hungry = Trueg = GoldFish()
g.move()  # 我的位置 9 4
s = Shark()
s.eat() # 吃货的梦想就是天天有得吃!
s.move()
# AttributeError: 'Shark' object has no attribute 'x'

解决该问题可用以下两种方式:

  • 调用未绑定的父类方法Fish.init(self)
class Shark(Fish):  # 鲨鱼def __init__(self):Fish.__init__(self)self.hungry = Truedef eat(self):if self.hungry:print("吃货的梦想就是天天有得吃!")self.hungry = Falseelse:print("太撑了,吃不下了!")self.hungry = True
  • 使用super函数super().init()
class Shark(Fish):  # 鲨鱼def __init__(self):super().__init__()self.hungry = Truedef eat(self):if self.hungry:print("吃货的梦想就是天天有得吃!")self.hungry = Falseelse:print("太撑了,吃不下了!")self.hungry = True

Python 虽然支持多继承的形式,但我们一般不使用多继承,因为容易引起混乱。

class DerivedClassName(Base1, Base2, Base3):statement-1...statement-N

需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,Python 从左至右搜索,即方法在子类中未找到时,从左到右查找父类中是否包含方法。

类对象:创建一个类,其实也是一个对象也在内存开辟了一块空间,称为类对象,类对象只有一个。

class A(object):pass

实例对象:就是通过实例化类创建的对象,称为实例对象,实例对象可以有多个。

class A(object):pass# 实例化对象 a、b、c都属于实例对象。
a = A()
b = A()
c = A()

类属性:类里面方法外面定义的变量称为类属性。类属性所属于类对象并且多个实例对象之间共享同一个类属性,说白了就是类属性所有的通过该类实例化的对象都能共享。

class A():a = 0  #类属性def __init__(self, xx):A.a = xx  #使用类属性可以通过 (类名.类属性)调用。

实例属性:实例属性和具体的某个实例对象有关系,并且一个实例对象和另外一个实例对象是不共享属性的,说白了实例属性只能在自己的对象里面使用,其他的对象不能直接使用,因为self是谁调用,它的值就属于该对象。

6.什么是绑定?

Python 严格要求方法需要有实例才能被调用,这种限制其实就是 Python 所谓的绑定概念。

Python 对象的数据属性通常存储在名为.__ dict__的字典中,我们可以直接访问__dict__,或利用 Python 的内置函数vars()获取.__ dict__。

7.一些相关的内置函数(BIF)

  • issubclass(class, classinfo) 方法用于判断参数 class 是否是类型参数 classinfo 的子类。
  • 一个类被认为是其自身的子类。
  • classinfo可以是类对象的元组,只要class是其中任何一个候选类的子类,则返回True。
  • hasattr(object, name)用于判断对象是否包含对应的属性。
  • getattr(object, name[, default])用于返回一个对象属性值。
  • setattr(object, name, value)对应函数 getattr(),用于设置属性值,该属性不一定是存在的。
  • delattr(object, name)用于删除属性。

class property([fget[, fset[, fdel[, doc]]]])用于在新式类中返回属性值。

  • fget – 获取属性值的函数
  • fset – 设置属性值的函数
  • fdel – 删除属性值函数
  • doc – 属性描述信息

四、魔法函数

魔法方法总是被双下划线包围,例如__init__。
魔法方法是面向对象的 Python 的一切,如果你不知道魔法方法,说明你还没能意识到面向对象的 Python 的强大。
魔法方法的“魔力”体现在它们总能够在适当的时候被自动调用。
魔法方法的第一个参数应为cls(类方法) 或者self(实例方法)。

  • cls:代表一个类的名称
  • self:代表一个实例对象的名称

1.基本的魔法方法

  • init(self[, …]) 构造器,当一个实例被创建的时候调用的初始化方法
class Rectangle:def __init__(self, x, y):self.x = xself.y = ydef getPeri(self):return (self.x + self.y) * 2def getArea(self):return self.x * self.yrect = Rectangle(4, 5)
print(rect.getPeri())  # 18
print(rect.getArea())  # 20
  • new(cls[, …]) 在一个对象实例化的时候所调用的第一个方法,在调用__init__初始化前,先调用__new__。
  • new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给__init
  • new__对当前类进行了实例化,并将实例返回,传给__init__的self。但是,执行了__new,并不一定会进入__init__,只有- __new__返回了,当前类cls的实例,当前类的__init__才会进入。

2.算术运算符

类型工厂函数,指的是“不通过类而是通过函数来创建对象”。

  • add(self, other)定义加法的行为:+
  • sub(self, other)定义减法的行为:-
  • mul(self, other)定义乘法的行为:*
  • truediv(self, other)定义真除法的行为:/
  • floordiv(self, other)定义整数除法的行为://
  • mod(self, other) 定义取模算法的行为:%
  • divmod(self, other)定义当被 divmod() 调用时的行为
  • divmod(a, b)把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。
  • pow(self, other[, module])定义当被 power() 调用或 ** 运算时的行为
  • lshift(self, other)定义按位左移位的行为:<<
  • rshift(self, other)定义按位右移位的行为:>>
  • and(self, other)定义按位与操作的行为:&
  • xor(self, other)定义按位异或操作的行为:^
  • or(self, other)定义按位或操作的行为:|

3.反函数运算符

反运算魔方方法,与算术运算符保持一一对应,不同之处就是反运算的魔法方法多了一个“r”。当文件左操作不支持相应的操作时被调用。

  • radd(self, other)定义加法的行为:+
  • rsub(self, other)定义减法的行为:-
  • rmul(self, other)定义乘法的行为:*
  • rtruediv(self, other)定义真除法的行为:/
  • rfloordiv(self, other)定义整数除法的行为://
  • rmod(self, other) 定义取模算法的行为:%
  • rdivmod(self, other)定义当被 divmod() 调用时的行为
  • rpow(self, other[, module])定义当被 power() 调用或 ** 运算时的行为
  • rlshift(self, other)定义按位左移位的行为:<<
  • rrshift(self, other)定义按位右移位的行为:>>
  • rand(self, other)定义按位与操作的行为:&
  • rxor(self, other)定义按位异或操作的行为:^
  • ror(self, other)定义按位或操作的行为:|

a + b
这里加数是a,被加数是b,因此是a主动,反运算就是如果a对象的__add__()方法没有实现或者不支持相应的操作,那么 Python 就会调用b的__radd__()方法。

4.增量赋值运算符

  • iadd(self, other)定义赋值加法的行为:+=
  • isub(self, other)定义赋值减法的行为:-=
  • imul(self, other)定义赋值乘法的行为:*=
  • itruediv(self, other)定义赋值真除法的行为:/=
  • ifloordiv(self, other)定义赋值整数除法的行为://=
  • imod(self, other)定义赋值取模算法的行为:%=
  • ipow(self, other[, modulo])定义赋值幂运算的行为:**=
  • ilshift(self, other)定义赋值按位左移位的行为:<<=
  • irshift(self, other)定义赋值按位右移位的行为:>>=
  • iand(self, other)定义赋值按位与操作的行为:&=
  • ixor(self, other)定义赋值按位异或操作的行为:^=
  • ior(self, other)定义赋值按位或操作的行为:|=

5.一元运算符

  • neg(self)定义正号的行为:+x
  • pos(self)定义负号的行为:-x
  • abs(self)定义当被abs()调用时的行为
  • invert(self)定义按位求反的行为:~x

6.属性访问

  • getattr(self, name): 定义当用户试图获取一个不存在的属性时的行为。
  • getattribute(self, name):定义当该类的属性被访问时的行为(先调用该方法,查看是否存在该属性,若不存在,接着去调用__getattr__)。
  • setattr(self, name, value):定义当一个属性被设置时的行为。
  • delattr(self, name):定义当一个属性被删除时的行为。

7.描述符

描述符就是将某种特殊类型的类的实例指派给另一个类的属性。

  • get(self, instance, owner)用于访问属性,它返回属性的值。
  • set(self, instance, value)将在属性分配操作中调用,不返回任何内容。
  • del(self, instance)控制删除操作,不返回任何内容。

8.定制序列

协议(Protocols)与其它编程语言中的接口很相似,它规定你哪些方法必须要定义。然而,在 Python 中的协议就显得不那么正式。事实上,在 Python 中,协议更像是一种指南。
容器类型的协议

  • 如果说你希望定制的容器是不可变的话,你只需要定义__len__()和__getitem__()方法。
  • 如果你希望定制的容器是可变的话,除了__len__()和__getitem__()方法,你还需要定义__setitem__()和__delitem__()两个方法。
  • len(self)定义当被len()调用时的行为(返回容器中元素的个数)。
  • getitem(self, key)定义获取容器中元素的行为,相当于self[key]。
  • setitem(self, key, value)定义设置容器中指定元素的行为,相当于self[key] = value。
  • delitem(self, key)定义删除容器中指定元素的行为,相当于del self[key]。

8.迭代器

  • 迭代是 Python 最强大的功能之一,是访问集合元素的一种方式。
  • 迭代器是一个可以记住遍历的位置的对象。
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
  • 迭代器只能往前不会后退。
  • 字符串,列表或元组对象都可用于创建迭代器:
for each in iter(links):print('%s -> %s' % (each, links[each]))
  • 迭代器有两个基本的方法:iter() 和 next()。
  • iter(object) 函数用来生成迭代器。
  • next(iterator[, default]) 返回迭代器的下一个项目。
  • iterator – 可迭代对象
  • default – 可选,用于设置在没有下一个元素时返回该默认值,如果不设置,又没有下一个元素则会触发 StopIteration 异常。
links = {'B': '百度', 'A': '阿里', 'T': '腾讯'}it = iter(links)
while True:try:each = next(it)except StopIteration:breakprint(each)# B
# A
# Tit = iter(links)
print(next(it))  # B
print(next(it))  # A
print(next(it))  # T
print(next(it))  # StopIteration

把一个类作为一个迭代器使用需要在类中实现两个魔法方法 iter() 与 next() 。

  • iter(self)定义当迭代容器中的元素的行为,返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
  • next() 返回下一个迭代器对象。
    StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 - next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
class Fibs:def __init__(self, n=10):self.a = 0self.b = 1self.n = ndef __iter__(self):return selfdef __next__(self):self.a, self.b = self.b, self.a + self.bif self.a > self.n:raise StopIterationreturn self.afibs = Fibs(100)
for each in fibs:print(each, end=' ')# 1 1 2 3 5 8 13 21 34 55 89

4.10 生成器

在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。

def myGen():print('生成器执行!')yield 1yield 2myG = myGen()
for each in myG:print(each)'''
生成器执行!
1
2
'''myG = myGen()
print(next(myG))
# 生成器执行!
# 1print(next(myG))  # 2
print(next(myG))  # StopIteration

用生成器实现斐波那契数列

def libs(n):a=0b=1while True:a,b=b,a+bif a>n:return yield alibs=libs(100)
for each in libs:print(each)

阿里天池Python训练营task03相关推荐

  1. 阿里天池 Python 训练营1

    阿里天池 Python 训练营1 位运算 位运算 位运算中的按位取反,比较复杂,涉及计算机内部数字的存储,补码,反码等等. print(~4) # 整数4,按位取反后是-5 为什么呢? 例如:-12= ...

  2. 阿里天池Python训练营-异常处理

    文章目录 1. Python 标准异常总结 2. Python标准警告总结 3. try - except 语句 执行次数 执行顺序 执行多个异常 4. try - except - finally ...

  3. 阿里天池-python训练营task1

    变量.运算符与数据类型 基础内容 位运算 位运算可以加速一些基本操作,但是复杂的操作用位运算来写会降低代码的可读性,一般都不会考虑位运算. 位运算一般是限制数值的表达 条件语句 都简单,不用说 ass ...

  4. 阿里云天池Python训练营(day10打卡)

    [ML&Py]×阿里云天池Python训练营(day10打卡)--Python数据分析:从0完成一个宝可梦数据分析实战 一.学习内容概览 1.1 学习地址:[阿里云天池python训练营](h ...

  5. 阿里云天池Python训练营

    阿里云天池Python训练营 本节主要介绍python中的数据分析方法,结合之前的学习内容,对于宝可梦精灵中的各种精灵数据进行分析,找寻其中的最强精灵.   一.数据分析实战 1. 数据集下载 !wg ...

  6. 阿里天池龙珠训练营打卡2

    阿里天池龙珠训练营打卡2 文章目录 列表添加元素 删除列表中的元素 获取列表的元素 列表的一些其他方法 字符串常用内置方法 字符串格式化 列表配合集合去重 列表添加元素 list.append(obj ...

  7. 阿里云天池 Python训练营Task4: Python数据分析:从0完成一个数据分析实战 学习笔记

    本学习笔记为阿里云天池龙珠计划Python训练营的学习内容,学习链接为:https://tianchi.aliyun.com/specials/promotion/aicamppython?spm=5 ...

  8. 阿里云天池 Python训练营Task3: Python基础进阶:从函数到高级魔法方法 学习笔记

    本学习笔记为阿里云天池龙珠计划Python训练营的学习内容,学习链接为:https://tianchi.aliyun.com/specials/promotion/aicamppython?spm=5 ...

  9. 阿里云天池 Python训练营Task2: Python基础练习:数据结构大汇总 学习笔记

    本学习笔记为阿里云天池龙珠计划Python训练营的学习内容,学习链接为:https://tianchi.aliyun.com/specials/promotion/aicamppython?spm=5 ...

最新文章

  1. ESXi6.7安装流程和bug处理
  2. CentOS 5.4 rsync+inotify配置触发式(实时)文件远程同步
  3. windows下spark开发环境配置
  4. 深度学习优化器 optimizer 的选择
  5. java字符串构造函数的应用_构造函数中的参数0需要找不到类型为'java.lang.String'的bean...
  6. Socket套接字实现服务器端连接
  7. Struts2框架中s:if标签和s:set标签小结
  8. xcode UIView常用方法属性动画
  9. php 支持泛型,PHP对Java样式类的泛型有答案吗?
  10. selenium+python在Windows的环境搭建
  11. Nginx面试题及基础
  12. 局域网桌面共享会议该如何实现屏幕共享?
  13. Python与爬虫有什么关系?
  14. js 判断是企业微信或微信
  15. 那些你所不知道的结构光技术
  16. 笔记本 - 常用快捷键 word 笔记
  17. Calendar加減月份、年份-月底的处理逻辑
  18. K8S 图形化管理界面 Kuboard
  19. c语言背景音乐,背景图,背景字体
  20. 国外工业互联网安全现状分析(政策;标准;厂商;产品)

热门文章

  1. Oasis 与 ThetaNuts 建立合作关系 | 为 DeFi 2.0 开辟道路
  2. Spring 5 中文解析之核心篇-Spring AOP编程
  3. apline更新下载软件报错ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.12/main: network error (check Internet
  4. CPU占用100%的原因及解决办法
  5. 8点1氪|亚马逊Q4业绩超预期;蔚来发行6.5亿美元可转债;微信春节推出表情红包...
  6. Elasticsearch 快速入门指南(二)
  7. css单位计算方法,CSS中的单位和百分比计算
  8. 基于ssm的模糊查询,解决中文乱码后可查询中文关键字
  9. 【开学导航】新生必备网课/考试作业答案查询攻略分享
  10. 想要成立新公司需要怎么注册?