python基础类型(三):可调用类型——函数和方法

一、可调用类型

在 python中所有的类型都是对象,即使是 int,float这些其他语言中的基础类型在 python中也是以对象的形式存在,函数和方法也不例外。

在 python中函数和方法是可调用类型的两个子集,可调用类型一共有 5种:

类型名称

描述

types.BuiltinFunctionType

内置函数或方法

type

内置类型和类的类型

object

所有类和类型的祖先

types.FunctionType

用户定义的函数

types.MethodType

类方法

最后两种就是我们常说的函数和方法,函数在类外被定义,而方法在类里面被定义,我们也可以说方法是类里面的函数,如:

# 在类外定义的是函数
def function_1():
    print("Hello World. This is a function.")

class TestClass:
    # 在类里面定义的是方法
    def function_2():
        print("Hello World. This is a method.")

需要注意的是,在 C++、JAVA这些面向对象的语言中函数和方法指的是同一个概念,它们没有像 python一样做出类型区分,只是在叫法上有些区别而已。

在这篇教程中我们只讲函数,至于方法等我们讲到类的时候再详细地讲,在这之前大家像用函数一样用方法就行。

二、函数的属性

前面我们讲到每个函数都是一个对象,对象自然有对应的属性:

  1. __doc__:函数的注释,就是紧挨着函数名的一个字符串,用来注释函数,文档生产工具可以根据这些字符串生成对应的文档,如: def f(name="name"): """ This is a function. """ pass print(f.__doc__) """ This is a function. """
  2. __name__:函数的名字,如: def function_name(): pass print(function_name.__name__) # function_name
  3. __defaults__:包含默认参数名的元组,如: def function_defaults(args_1, args_2='name'): pass print(function_defaults.__defaults__) # ('name',)

三、函数的参数

函数的参数有两种,位置参数和关键字参数,这两者又分为有默认值和没有默认值两种类型。

位置参数和关键字参数的主要区别是,位置参数在传递的时候可以不指定变量名,而是按照约定的顺序进行赋值,而关键字参数必须指定变量名才能对其进行赋值,如:

def function_args(a1, a2):
    print("a1:", a1, "a2", a2)
    
function_args('1','2')
# a1: 1 a2 2
# a1和 a2都是位置参数,第一个参数赋值给 a1,第二个参数赋值给 a2

def function_keyword_args(a1, *, a2):
    print("a1:", a1, "a2", a2)
    
function_keyword_args('1', a2='2')
# 此时再使用 function_keyword_args('1', '2')会报错
# 因为 a2是关键字参数,必须指定变量名

所有的参数默认为位置参数,只有当使用 *分隔时后面的参数才会被看作关键字参数。

注意:

在定义函数时上面四种参数的书写顺序是有严格限制的,位置参数必须声明在最前面,同时有默认值的参数必须在没有默认值的参数后面,如:

def function_args(a1, a2='2', *, a3, a4='4'):
    print("a1:", a1, "a2", a2, "a3:", a3, "a4:", a4)

# 下面的定义是错误的
# 有默认值的参数在前
def function_args(a2='2', a1, *, a3, a4='4'):
    print("a1:", a1, "a2", a2, "a3:", a3, "a4:", a4)

当我们有很多参数要传递给函数时,我们可能会写出这样的代码:

def function_args(a1, a2, a3, a4, a5, a6, *, b1, b2, b3, b4):
    pass

function_args(1, 2, 3, 4, 5, 6, b1=1, b2=2, b3=3, b4=4)

这样的代码可以说是很糟糕的代码了,这时我们可以使用 ***来简化我们的代码,如:

def function_args(a1, a2, a3, a4, a5, a6, *, b1, b2, b3, b4):
    pass

args = [1, 2, 3, 4, 5, 6]
# 或者 args = (1, 2, 3, 4, 5, 6)
keyword_args = {
    'b1': 1,
    'b2': 2,
    'b3': 3,
    'b4': 4
}

function_args(*ags, **keyword_args)

*的操作对象是列表或者元组,用来传递位置参数,**的操作对象是字典,用来传递关键字参数。

四、函数作为变量使用

既然函数是一种特殊的变量类型,那变量所具有的操作肯定也可以应用到函数上,比如:

  1. 赋值给其他变量: def say_hello(): print("Hello World") say_hello_2 = say_hello say_hello_2() # Hello World
  2. 作为参数传递 def say_hello(): print("Hello World") def execute_func(func): func() execute_func(say_hello) # Hello World

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏伦少的博客

scala 下划线使用指南

原文地址:https://my.oschina.net/joymufeng/blog/863823   作者:joymufeng

3598
来自专栏Golang语言社区

【Golang语言社区】前端编程-javascript使用闭包模拟私有属性和方法

最近因为做了一个项目,其中涉及到了js私有方法,这个概念在其语言里面是很常见的,很多语言都有private这个关键字,只要在一个类的前面加上private就表示...

3079
来自专栏C#

解析C#类中的构造函数

《解析C#类中的构造函数》 一.  C#中的构造函数概述: C#中类包含数据成员和函数成员。函数成员提供了操作类中数据的某些功能,包括方法、属性、构造器和终结器...

2035
来自专栏小二的折腾日记

day5(面向对象2)

572
来自专栏PHP在线

php数组和字符串操作

抽象类 1.抽象类不能实例化 2.抽象方法必须被子类重写的方法 3.如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否包含其他一般方法。 抽象类通常代表一...

3487
来自专栏步履前行

Java基础系列---static关键字

  今天在和同事讨论的时候谈到了关于static的问题,正巧自己有一些忘记了,就特来学习一番。

1304
来自专栏C语言及其他语言

【每日一题】问题 1117: K-进制数

考虑包含N位数字的K-进制数. 定义一个数有效, 如果其K-进制表示不包含两连续的0.

1002
来自专栏HTML5学堂

JavaScript | 获取数组中的单词并统计出现次数

HTML5学堂(码匠):如何通过JavaScrip实现数组元素的查找?在一个数组当中,找到所有的单词,并统计每个单词出现的次数。 功能需求 在一个自定义数组...

4977
来自专栏编程

深入理解 Python 的属性查找

今天我们了解下python的属性查找,在Python中,属性查找(attribute lookup)是比较复杂的,特别是涉及到描述符descriptor的时候。...

23910
来自专栏小鹏的专栏

用一个脚本学习 python

# -*- coding: utf-8 -*- # Python 2.7 学习参考脚本 # print 打印函数 print "Hello Worl...

2907

扫码关注云+社区

领取腾讯云代金券