跳至主要內容

Python

LincZero大约 6 分钟

Python

目录

函数式编程(封装)

内置函数(内嵌在解释器中)

查看所有内置函数

三种方法:

内置辅助工具

内置函数里有很多辅助开发、调试、学习的工具。而且很多都是==【Python特有】==的

  • 查看变量的数据类型的所有方法dir(var)

    • var可以是具体的变量,如1、'str'

    • 也可以是type的结果,如str、list、tuple、dict、setint、float、bool、complex

      (这些type不是关键词,是一种被初始化了的自带变量,可以被重赋值,重赋值后以重赋值的值为准)

    • 也可以为空,提示里面可以填的特殊值,比如__builtins__能查看所有python内置函数

  • 查看变量的数据类型的某一方法用处help(var[.method])

    • var可以是具体的变量,如1、'str'

    • 也可以是type的结果,如str、list、tuple、dict、setint、float、bool、complex

      (这些type不是关键词,是一种被初始化了的自带变量,可以被重赋值,重赋值后以重赋值的值为准)

    • 也可以不填方法,只传var

    • 也可以为空,进入连续输入模式

    • 查看时

      • append(self, object, /)insert(self, index, object, /),可以知道传哪些变量
      • sort(*, key=None, reverse=False)
  • 变量类型

    • type函数:type(var),var是具体的变量
    • 也可以直接输入type查看是否有这种类型,如str、list、tuple、dict、setint、float、bool、complex
  • 变量的id或地址值id(var)

  • 查看模块名__name__属性,其中main文件的该属性值为__main__而非文件名

  • 查看值所属的类object.__class__

  • 查看相关文档__doc__属性(基于文档字符串)

  • 查看函数注解__annotations__属性(基于函数注解)

输入输出

python的输入输出函数的内置函数(C语言的是标准库函数)

  • 输入input()函数
  • 输出print()函数
    • 原始字符串
    • 格式化输出
  • python2区别:python2的print可以不包含括号(python3必须包含)

自定义函数

字面量形式

  • 定义:def function_name(argument):
  • 调用:function_name()
  • 顺序:先定义再调用(无需声明原型)

补充

  • 形参声明(不同于C)

    • 形参不用声明类型
  • 传参方式

    • 位置传参:声明:def fun(arg1,arg2):,调用:fun(1,2)

    • 关键字传参:声明:def fun(arg1,arg2):,调用:fun(arg1=1,arg2=2)

    • 可不传参(默认参):声明:def fun(arg1=1,arg2=2):

      • 重要警告【大坑】:默认值只会被赋值一次(相当于局部静态变量)

        这使得当默认值是可变对象时会不同,比如:

        def f(a, L=[]):
            L.append(a)
            return L
        
        print(f(1))  # [1]
        print(f(2))  # [1, 2]
        print(f(3))  # [1, 2, 3]
        

        如果不想累积,则应将默认值变为不可变对象

        def f(a, L=None):
            if L is None:
                L = []
            L.append(a)
            return L
        
    • 任意数量传参(类似于Js ES6中的rest参数)

      • 列表型:声明:def fun(arg1,list):,调用:fun(1,[2,3])
      • 封装到元组:声明:def fun(arg1,*args):,参数自动封装到元组中,调用:fun(1,2,3)
      • 封装到二维元组:声明:def fun(arg1,**args):,参数自动封装到二维元组中,调用:fun(1,a=2,b=3)
  • 返回(不同于C)

    • 无需定义函数时声明:是否有返回值、和返回值类型
    • return后面可为空,来表示返回None

Lambda形式

  • 简概

    • 与C++中的Lambda函数类似,可以创建短小的匿名函数
  • 使用

    • 举例:sum = lambda a, b: a+b返回两个参数的和
  • 作用

    • 能进行嵌套函数定义
    • 可以中外部作用域引用变量(可不受作用域影响函数内部引用外部变量,可以理解为是Lambda是调用了另一个在全局的函数)
  • 应用举例

    self.aboutAct = QAction("关于", self, statusTip="关于界面"
                                    , triggered=lambda: QMessageBox.about(self, "About MDI", "WWWWWWWWWWWWW")
                                    )  # def about(self);
    

函数的装饰器

参考:https://zhuanlan.zhihu.com/p/311503904

@property

作用

调用方法改为了调用对象即 p.name() 改为了 p.name

即当obj.function1时自动触发 @property def 中的方法

应用场景

好像还有让成员延迟初始化的作用??

@xxx.setter

作用

@name.setter 装饰器不仅将调用方法改为了获取指定对象的属性即 p.name3 对应于 p.name() 亦 p.name。

此外,对其赋值时相当于调用了方法, 即有 p.name3 = n 对应于 p.name3(n)

即当obj.attr1 = 时自动触发 @attr1.setter 中的方法

应用场景

# 比如令
title = xxx
# 时,自动进行以下操作
title = xxx
grTitle = xxx+1

# 有点接近C++的等号运算符重载但也不是
# python的方便很多

@xxx.getter

同理setter,还没setter复杂

而且@property应该就是@xxx.getter吧

使用举例

@property

class T:
    def __init__(self):
        self._x = 12
    @property
    def x(self):
        print("property")
        return self._x

        
# sehll
t = T()
t			# <__main__.T object at 0x000002ACD3B41188>
print(t._x) # 12
print(t.x)  # property    12
t.x = 58		# 报错:AttributeError: can't set attribute。因为没有这个变量,t.x调用的是方法
t._x = 58		# 不报错
print(t._x) # 58
print(t.x)  # property    58

@x.setter

class T:
    """
    本质
    	实际存储的是变量 _x
    	但无论是设置值还是获取值,都是字面量都是 x
    意义
    	1:相当于做了一层封装不直接暴露数据、暴露的是函数,一个字面量优化过的函数
    	2:相当于数据绑定。
    		Vue中的视图绑定数据或数据绑定数据,这里只要_x一变多个绑定他的数据都会自动改变
    		也能绑定操作,例如 self.title = title 时自动改变某对象的标题
    	3:不要init _x。只能先set后get,否则崩溃
    """
    def __init__(self):
        self._x = 12
    @property
    def x(self):
        print("property")
        return self._x
    @x.setter
    def x(self, value):
        print("set")
        self._x = value
        
# sehll
t = T()
t			# <__main__.T object at 0x000002ACD3B41188>
print(t._x) # 12
print(t.x)  # property    12
t.x = 58		# 不报错
t._x = 58		# 不报错
print(t._x) # 58
print(t.x)  # property    58

其他

class Person:
    def __init__(self, name):
        self.name1 = name
        self.name2 = '小白'

    # 利用property装饰器将获取name方法转换为获取对象的属性
    @property
    def name(self):
        return self.name1 + '!'

    # 利用property装饰器将设置name方法转换为获取对象的属性
    @name.setter  # @属性名.setter
    def name3(self, n):
        self.name1 = '小绿' if n == '小灰' else '小宝'


p = Person('小黑')
print(p.name, p.name1, p.name2, p.name3)
p.name3 = '小灰' 
print(p.name, p.name1, p.name2, p.name3)
p.name3 = '小2' 
print(p.name, p.name1, p.name2, p.name3)
p.name = '123'

不支持函数重载

Python 不支持函数重载,而其他语言大都支持

如果我们在同一命名空间中定义的多个函数是同名的,最后一个将覆盖前面的各函数,也就是函数的名称只能是唯一的

原因

函数重载主要是为了解决两个问题。

  1. 可变参数类型
    • Python中不需要处理,python可以接受任何类型的参数
  2. 可变参数个数
    • 可以使用缺省参数

补充

Python3是可以通过metaclass + parameter annotation使某个类假装支持function overloading