函数
函数文档:
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是形参
print(MyFirstFunction.__ doc__)#输出函数MyFirstFunction内的字符串?
参数
- 位置参数 (positional argument):普通参数
- 默认参数 (default argument): 默认参数 = 默认值,调用函数时,默认参数的值如果没有传入,则被认为是默认值。默认参数一定要放在位置参数 后面,不然程序会报错。
- 可变参数 (variable argument):可变参数就是传入的参数个数是可变的,可以是 0, 1, 2 到任意个,是不定长的参数。声明:( *args ) ,实际调用时可以零到任意个,自动组装成元组。
- 关键字参数 (keyword argument):声明:( **kw ),实际调用也可以是零到任意个,自动组装成字典。每一对键值对用“key=value”输入。
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}
- 命名关键字参数 (name keyword argument):限制关键字参数的名字,使用命名关键字参数时,要特别注意不能缺少参数名。声明:( *, 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
在 Python 中定义函数,可以用位置参数、默认参数、可变参数、命名关键字参数和关键字参数,这 5 种参数中的 4 个都可以一起使用,但是注意,参数定义的顺序必须是:
- 位置参数、 默认参数、 可变参数、 关键字参数。
- 位置参数、 默认参数、 命名关键字参数、 关键字参数。
变量作用域
当内部作用域想修改外部作用域的变量时,要用到 global 和 nonlocal 关键字。
global:在函数内要使用或修改全局变量num,需要在函数内声明:global num
内嵌函数:在某个函数内部被定义的函数,只能在该函数内部被调用。
闭包:如果在一个内部函数里对外层非全局作用域的变量进行引用,那么内部函数就被认为是闭包。 闭包的返回值通常是函数。
def funX(x):
def funY(y):
return x * y
return funY
i = funX(8)# i 相当于funY(y):return 8*y,所以是个函数
print(type(i)) # <class 'function'>
print(i(5)) # 40
nonlocal 关键字,修改闭包作用域中的变量,和global类似
递归,设置递归层数,Python默认递归层数为 100
import sys
sys.setrecursionlimit(1000)
匿名函数
定义:
lambda argument_list: expression
形式为“关键词 输入参数:表达式”
用法跟普通函数差不多,不需要return
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)) # 30
func = lambda *args: sum(args)
print(func(1, 2, 3, 4, 5)) # 15
匿名函数 常常应用于函数式编程的高阶函数 (high-order function)中,主要有两种形式:
- 参数是函数 (filter, map)
- 返回值是函数 (closure)
filter(function, iterable) 过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象
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]
也可以自定义高阶函数:
def apply_to_list(fun, some_list):
return fun(some_list)
lst = [1, 2, 3, 4, 5]
print(apply_to_list(sum, lst))
# 15
print(apply_to_list(len, lst))
# 5
print(apply_to_list(lambda x: sum(x) / len(x), lst))
# 3.0
类与对象
class Turtle: # Python中的类名约定以大写字母开头
"""关于类的一个简单例子"""
# 属性
color = 'green'
weight = 10
# 方法
def climb(self):
print('我正在很努力的向前爬...')
def run(self):
print('我正在飞快的向前跑...')
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__)
# Turtle
tt.climb()
# 我正在很努力的向前爬...
# Python类也是对象。它们是type的实例
print(type(Turtle))
# <class 'type'>
继承:子类自动共享父类之间数据和方法的机制
多态:不同对象对同一方法响应不同的行动
self
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
self 代表的是类的实例,代表当前对象的地址
init(self[, param1, param2…]):该方法在类实例化时会自动调用。以下#1#2的效果是一样的:
#1
class Ball:
def setName(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball()
a.setName("球A")
#2
class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball("球A")
公有和私有
在 Python 中定义私有变量只需要在变量名或函数名前加上“__”两个下划线,那么这个函数或变量就会为私有的了。
类的私有属性实例:
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count() # 1
counter.count() # 2
print(counter.publicCount) # 2
print(counter._JustCounter__secretCount) # 2 Python的私有为伪私有
print(counter.__secretCount)
# AttributeError: 'JustCounter' object has no attribute '__secretCount'
类的私有方法实例:
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def 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_MYP
x.foo()
# 这是公共方法
# 这是私有方法
x.__foo()
# AttributeError: 'Site' object has no attribute '__foo'
继承
语法:
class 派生类名(基类名)
____…
如果没有合适的基类,就使用object类,这是所有类最终都会继承的类
可以继承多个类: class C(A, B): # 继承类 A 和 B
复写
如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。
解决方法:
- 在子类的同名方法中调用未绑定的父类方法,比如
Fish.__init__(self)
- 使用super函数,
super().__init__()
一些相关的内置函数(BIF)
issubclass(class, classinfo):判断参数 class 是否是类型参数 classinfo 的子类,一个类被认为是其自身的子类。
classinfo 可以是类对象的元组,只要class是其中任何一个候选类的子类,则返回 True。
isinstance(object, classinfo) 方法用于判断一个对象是否是一个已知的类型,类似 type()。
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
如果第一个参数不是对象,则永远返回 False 。
如果第二个参数不是类或者由类对象组成的元组,会抛出一个 TypeError 异常。
hasattr(object, name) 用于判断对象是否包含对应的属性。
getattr(object, name[, default]) 用于返回一个对象属性值
class A(object):
bar = 1
a = A()
print(getattr(a, 'bar')) # 1
print(getattr(a, 'bar2', 3)) # 3
print(getattr(a, 'bar2'))
# AttributeError: 'A' object has no attribute 'bar2'
setattr(object, name, value) 用于设置属性值,该属性不一定是存在的。
delattr(object, name) 用于删除属性。
魔法方法:
被下划线包围,能在适当的时候被自动调用。
第一个参数应为cls (类方法) 或者 self (实例方法)。
cls :代表一个类的名称
self :代表一个实例对象的名称
__init__(self[, ...])
构造器,当一个实例被创建的时候调用的初始化方法
__new__(cls[, ...])
在一个对象实例化的时候所调用的第一个方法,在调用 init 初始化前,先调用 new 。
- new 至少要有一个参数 cls ,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给 init 。
- new 对当前类进行了实例化,并将实例返回,传给 init 的 self 。但是,执行了 new ,并不一定会进入 init ,只有 new 返回了,当前类 cls 的实例,当前类的 init 才会进入。
- 若 new 没有正确返回当前类 cls 的实例,那 init 是不会被调用的,即使是父类的实例也不行,将没有 init 被调用。
new 方法主要是当你继承一些不可变的 class 时(比如 int, str, tuple ), 提供给你一个自定义这些类的实
例化过程的途径。
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return str.__new__(cls, string)
a = CapStr("i love lsgogroup")
print(a) # I LOVE LSGOGROUP
__del__(self)
:析构器,当一个对象将要被系统回收之时调用的方法。
__str__(self)
:
- 当你打印一个对象的时候,触发
__str__
- 当你使用 %s 格式化的时候,触发
__str__
- str 强转数据类型的时候,触发
__str__
__repr__(self)
:
- repr 是 str 的备胎
- 有 str 的时候执行 str ,没有实现 str 的时候,执行 repr
- repr(obj) 内置函数对应的结果是 repr 的返回值
- 当你使用 %r 格式化的时候 触发 repr
str(self) 的返回结果可读性强。也就是说, str 的意义是得到便于人们阅读的信息。
repr(self) 的返回结果应更准确。 repr 存在的目的在于调试,便于开发者使用。
class Cat:
"""定义一个猫类"""
def __init__(self, new_name, new_age):
"""在创建完对象之后 会自动调用, 它完成对象的初始化的功能"""
self.name = new_name
self.age = new_age
def __str__(self):
"""返回一个对象的描述信息"""
return "名字是:%s , 年龄是:%d" % (self.name, self.age)
def __repr__(self):
"""返回一个对象的描述信息"""
return "Cat:(%s,%d)" % (self.name, self.age)
tom = Cat("汤姆", 30)
print(tom) # 名字是:汤姆 , 年龄是:30
print(str(tom)) # 名字是:汤姆 , 年龄是:30
print(repr(tom)) # Cat:(汤姆,30)