python之函数与面向对象

1 函数

1.1 函数基础

  • 定义
 def 函数名():
     代码1
     代码2
     ...
  • 调用
    函数名()
  • 函数的说明文档
  def 函数名():
      """ 函数说明文档 """
  • 查看函数的说明文档
  help(函数名)

1.2 变量的作用域

  • 局部变量

    • 所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。
  • 全局变量

    • 所谓全局变量,指的是在函数体内、外都能生效的变量。
  • 如何在函数体内部修改全局变量?

a = 100
def testA():
    print(a)
def testB():
    # global 关键字声明a是全局变量
    global a
    a = 200
    print(a)
testA()  # 100
testB()  # 200
print(f'全局变量a = {a}')  # 全局变量a = 200

1.3 函数的返回值

  • return a, b写法,返回多个数据的时候,默认是元组类型
  • return后面可以连接列表、元组或字典,以返回多个值。

1.4 函数的参数

1.4.1 位置参数

  • 位置参数:调用函数时根据函数定义的参数位置来传递参数。
    • 传递和定义参数的顺序及个数必须一致。

1.4.2 关键字参数

  • 通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
def user_info(name, age, gender):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)
  • 函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。

1.4.3 缺省参数

  • 缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值
  • 所有位置参数必须出现在默认参数前,包括函数定义和调用
def user_info(name, age, gender='男'):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('TOM', 20)
user_info('Rose', 18, '女')

1.4.4 不定长参数

  • 包裹位置传递
def user_info(*args):
    print(args)


# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)

注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。

  • 包裹关键字传递
def user_info(**kwargs):
    print(kwargs)


# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)

综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。

1.5 拆包和交换变量值

1.5.1 拆包

  • 拆包:元组
def return_num():
    return 100, 200


num1, num2 = return_num()
print(num1)  # 100
print(num2)  # 200
  • 拆包:字典
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1

# 对字典进行拆包,取出来的是字典的key
print(a)  # name
print(b)  # age

print(dict1[a])  # TOM
print(dict1[b])  # 18

1.5.2 交换变量值

a, b = 1, 2
a, b = b, a
print(a)  # 2
print(b)  # 1

1.6 引用

  • 在python中,值是靠引用来传递来的。

  • 我们可以用id()来判断两个变量是否为同一个值的引用。

  • 我们可以将id值理解为那块内存的地址标识。

1.6.1 引用当做实参

def test1(a):
    print(a)
    print(id(a))

    a += a

    print(a)
    print(id(a))


# int:计算前后id值不同
b = 100
test1(b)

# 列表:计算前后id值相同
c = [11, 22]
test1(c)

1.6.2 可变类型与不可变类型

所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变.

  • 可变类型
    • 列表
    • 字典
    • 集合
  • 不可变类型
    • 整型
    • 浮点型
    • 字符串
    • 元组

1.7 lambda表达式

1.7.1 lambda语法

  • lambda 参数列表 : 表达式
  • lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。
  • lambda表达式能接收任何数量的参数但只能返回一个表达式的值。

1.7.2 lambda的参数形式

  • 无参数
fn1 = lambda: 100
print(fn1())
  • 一个参数
fn1 = lambda a: a
print(fn1('hello world'))
  • 默认参数
fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))
  • 可变参数:*args
fn1 = lambda *args: args
print(fn1(10, 20, 30))

注意:这里的可变参数传入到lambda之后,返回值为元组。

  • 可变参数:**kwargs
fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))

1.7.3 lambda的应用

  • 带判断的lambda
fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))
  • 列表数据按字典key的值排序
students = [
    {'name': 'TOM', 'age': 20},
    {'name': 'ROSE', 'age': 19},
    {'name': 'Jack', 'age': 22}
]

# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)

# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)

# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)

1.8 高阶函数

  • 把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。
def sum_num(a, b, f):
    return f(a) + f(b)


result = sum_num(-1, 2, abs)
print(result)  # 3
  • 函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。

1.8.1 内置高阶函数

  • map(func, lst):
    • 参数一:函数
    • 参数二:容器
    • 返回值:新容器
  • reduce(func,lst)
    • 参数一:函数
    • 参数二:容器
    • 返回值:value
  • filter(func, lst)
    • 参数一:函数
    • 参数二:容器
    • 返回值:容器

2. 面向对象

2.1 类

Python中类分为:经典类(不推荐) 和 新式类

  • 语法
class 类名():
    代码
    ......

注意:类名要满足标识符命名规则,同时遵循大驼峰命名习惯

  • 体验
class Washer():
    def wash(self):
        print('我会洗衣服')
  • 拓展:经典类

不由任意内置类型派生出的类,称之为经典类

class 类名:
    代码
    ......

2.1.1 创建对象

对象又名实例。

  • 语法
对象名 = 类名()

2.1.2 self

self指的是调用该函数的对象

2.2 添加和获取对象属性

  • 类外面添加对象属性
对象名.属性名 =
  • 类外面获取对象属性
对象名.属性名
  • 类里面获取对象属性
self.属性名
  • 类里面设置对象属性
self.属性名=

2.3 魔法方法

在Python中,__xx__()的函数叫做魔法方法,指的是具有特殊功能的函数。

2.3.1 __init__()

  • 初始化对象

  • 在创建一个对象时默认被调用

  • __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。

  • 还可以带其他参数__init__(self, width, height)

2.3.2 __str__()

  • 当使用print输出对象的时候,默认打印对象的内存地址。
  • 如果类定义了__str__方法,那么就会打印从在这个方法中 return 的数据。

2.3.3 __del__()

  • 当删除对象时,python解释器也会默认调用__del__()方法。

2.4 继承

不由任意内置类型派生出的类,称之为经典类。

class 类名:
    代码
    ......
  • 拓展2:新式类
class 类名(object):
  代码
  • 在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。

2.4.1 多继承

class Prentice(School, Master):
    pass
  • 注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。

2.4.2 子类调用父类的同名方法和属性

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        # 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    # 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
    def make_master_cake(self):
        Master.__init__(self)     # python2.0中的方式,不推荐使用了
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


daqiu = Prentice()

daqiu.make_cake()

daqiu.make_master_cake()

daqiu.make_school_cake()

daqiu.make_cake()

2.4.3 多层继承

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


# 徒孙类
class Tusun(Prentice):
    pass


xiaoqiu = Tusun()

xiaoqiu.make_cake()

xiaoqiu.make_school_cake()

xiaoqiu.make_master_cake()

2.4.2 supper()

  • python3新加的,代替了之前的调用父类同名属性和方法方式
  • 使用super() 可以自动查找父类。调用顺序遵循 __mro__ 类属性的顺序。比较适合单继承使用。
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(Master):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')

        # 方法2.1
        # super(School, self).__init__()
        # super(School, self).make_cake()

        # 方法2.2
        super().__init__()
        super().make_cake()


class Prentice(School):
    def __init__(self):
        self.kongfu = '[独创煎饼果子技术]'

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    # 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)

    # 一次性调用父类的同名属性和方法
    def make_old_cake(self):
        # 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
        # Master.__init__(self)
        # Master.make_cake(self)
        # School.__init__(self)
        # School.make_cake(self)

        # 方法二: super()
        # 方法2.1 super(当前类名, self).函数()
        # super(Prentice, self).__init__()
        # super(Prentice, self).make_cake()

        # 方法2.2 super().函数()
        super().__init__()
        super().make_cake()


daqiu = Prentice()

daqiu.make_old_cake()

2.5 私有权限

2.5.1 定义私有属性和方法

  • 设置私有权限:设置某个实例属性或实例方法不继承给子类。
  • 在属性名和方法名 前面 加上两个下划线 __。
  • python中的私有属性其实时伪私有属性,还是可以访问到,访问方式为 _类名__私有属性

2.5.2 获取和修改私有属性值

  • 在Python中,一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值。

2.6 类属性

2.6.1 设置和访问类属性

  • 类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有
  • 类属性可以使用 类对象实例对象 访问。
class Dog(object):
    tooth = 10


wangcai = Dog()
xiaohei = Dog()

print(Dog.tooth)  # 10
print(wangcai.tooth)  # 10
print(xiaohei.tooth)  # 10

类属性的优点

  • 记录的某项数据 始终保持一致时,则定义类属性。
  • 实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有 ,仅占用一份内存更加节省内存空间

2.6.2 修改类属性

类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。

class Dog(object):
    tooth = 10


wangcai = Dog()
xiaohei = Dog()

# 修改类属性
Dog.tooth = 12
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 12
print(xiaohei.tooth)  # 12

# 不能通过对象修改属性,如果这样操作,实则是创建了一个实例属性
wangcai.tooth = 20
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 20
print(xiaohei.tooth)  # 12

2.7 实例属性

class Dog(object):
    def __init__(self):
        self.age = 5

    def info_print(self):
        print(self.age)


wangcai = Dog()
print(wangcai.age)  # 5
# print(Dog.age)  # 报错:实例属性不能通过类访问
wangcai.info_print()  # 5

2.8 类方法

2.8.1 类方法特点

  • 需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。

2.8.2 类方法使用场景

  • 当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
  • 类方法一般和类属性配合使用
    -一个对象访问某个属性时,首先查找对象属性,找不到才会查找类属性
  • 不推荐通过对象获取类属性:当赋值时可能有些歧义
class Dog(object):
    __tooth = 10

    @classmethod
    def get_tooth(cls):
        return cls.__tooth


wangcai = Dog()
result = wangcai.get_tooth()
print(result)  # 10

2.9 静态方法

2.9.1 静态方法特点

  • 需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)
  • 静态方法 也能够通过 实例对象类对象 去访问。
  • 总结
    • 如果一个方法需要访问对象属性,则可以设置为对象方法
    • 若果一个方法需要访问类属性,则可以设置为类方法
    • 如果一个方法既不访问对象属性也不访问类属性,则可以设置为静态方法

2.9.2 静态方法使用场景

  • 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
  • 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
class Dog(object):
    @staticmethod
    def info_print():
        print('这是一个狗类,用于创建狗实例....')


wangcai = Dog()
# 静态方法既可以使用对象访问又可以使用类访问
wangcai.info_print()
Dog.info_print()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值