人生苦短之我用Python篇(遍历、函数、类)

#遍历

info = {'key1':'value1','key2':'value2','key3':'value3'}
#方式一
for i in info:
    print(i,info[i])
#方式二
for key,value in info.items():
    print(key,value)

li = [1,2,3,5,4,7,9,7]
for index,v in enumerate(li):
print(index,v)

函数:


*定义函数,函数体不执行,只有调用函数时,函数体才执行。

#写一个监控程序,监控服务器的系统状况,当cpu\disk\memory等指标的使用量超过阀值时即发邮件报警
#不使用函数版
while True:
    if cpu利用率 > 90%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
     
    if 硬盘使用空间 > 90%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
     
    if 内存占用 > 80%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
#以上代码存在问题:

    #1.代码重复过多,一个劲的copy and paste不符合高端程序员的气质
    #2.如果日后需要修改发邮件的这段代码,比如加入群发功能,那你就需要在所有用到这段代码的地方都修改一遍

#函数版
def 发送邮件(内容)
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
     
while True:
     
    if cpu利用率 > 90%:
        发送邮件('CPU报警')
     
    if 硬盘使用空间 > 90%:
        发送邮件('硬盘报警')
     
    if 内存占用 > 80%:
        发送邮件('内存报警')
为什么需要函数?
函数是什么?

函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子过程或子程序),在Pascal中叫做procedure(过程)和function,在C中只有function,在Java里面叫做method。

定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

特性:

  1. 减少重复代码
  2. 使程序变的可扩展
  3. 使程序变得易维护

语法:

def say():      #定义函数,def为关键词,say为函数名
    print("Hello,my name is ChenTaicheng,I'm fine,Thank you.")      #函数内容,为一系列语句

say()       #调用函数

带参数

#下面这段代码
a,b = 5,8
c = a**b
print(c)
 
 
#改成用函数写
def calc(x,y): #该函数可以接受传入两个参数,即x,y,多一个不行,少一个也不行
    res = x**y
    return res #返回函数执行结果
 
c = calc(a,b) #结果赋值给c变量
print(c)

形参与实参

形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

默认参数

def stu_register(name, age, course, country='CN'):#定义函数时设置默认参数
    print("----注册学生信息------")
    print("姓名:", name)
    print("age:", age)
    print("国籍:", country)
    print("课程:", course)


stu_register("张三", 22, "python_devops","美国")#有传值则使用传入的值
stu_register("李四", 21, "linux")#没有传值则使用默认参数
stu_register(age=22,name='CCIE',course="python",) #使用指定参数名赋值,里面的参数就得都使用指定参数名赋值的方式
 

非固定参数:*args    *keyargs

非固定参数
若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数
def stu_register(name,age,*args): # *args 会把多传入的参数变成一个元组形式
    print(name,age,args)

stu_register('ctc',22) #输出 ctc 22 (),后面这个()就是args,只是因为没传值,所以为空
stu_register('ctc',22,'python','qypt') #输出 ctc 22 ('python', 'qypt')

还可以有一个**kwargs
def stu_register(name,age,*args,**kwargs): # *kwargs 会把多传入的参数变成一个dict形式
    print(name,age,args,kwargs)

stu_register('ctc',22) #输出ctc 22 () {},{}#后面这个{}就是kwargs,只是因为没传值,所以为空
stu_register('ctc',22,'python','qypt') #输出 ctc 22 ('python', 'qypt') {}
stu_register('ctc',22,'python',school = 'qypt',sex = 'man') #ctc 22 ('python',) {'school': 'qypt', 'sex': 'man'}

全局变量与局部变量

'''
全局与局部变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
'''
name = "ChenTaicheng"  #全局变量


def change_name(name):
    print("before change:", name)
    name = "一个改变世界的人"  #局部变量
    print("after change", name)


change_name(name)

print("在外面看看name改了么?", name)

----------------------------------------------------------------------------------------------------------------------------------------------------------》
输出结果:
before change: ChenTaicheng
after change 一个改变世界的人
在外面看看name改了么? ChenTaicheng

递归与返回值

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

递归特性:

1. 必须有一个明确的结束条件

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

要想获取函数的执行结果,就可以用return语句把结果返回

注意:

  1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
  2. 如果未在函数中指定return,那这个函数的返回值为None
def calc(n):
    print(n)
    if int(n / 2) == 0:
        return n
    return calc(int(n / 2))


f = calc(10)
print(f)  #输出函数的返回值

输出:
10
5
2
1
1  #函数的返回值

匿名函数 :匿名函数就是不需要显式的指定函数

#这段代码
def calc(n):
    return n**n
print(calc(10))
 
#换成匿名函数
calc = lambda n:n**n
print(calc(10))
你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下
res = map(lambda x:x**2,[1,5,7,4,8])
for i in res:
    print(i)

高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

def add(x,y,f):
    return f(x) + f(y)
 
 
res = add(3,-6,abs)  #即把一个函数名当中参数值,abs为求绝对值的函数的函数名
print(res)

 装饰器:

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
它经常用于有切面需求的场景,比如:插入日志、性能测试、事务
处理、缓存、权限校验等场景。
装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出
大量与函数功能本身无关的雷同代码并继续重用。
概括的讲,装饰器的作用就是为已经存在的对象
添加额外的功能。
# 一个简单的例子
# def foo():
#     print("I'm foo")
#
# foo()

# 现在有新需求,需要添加一个新功能
# def foo():
#     print("NEW function")
#     print("I'm foo")
#
# foo()
#如果Bar1(),Bar2()也需要添加这个新功能,此时就需要在每个函数里添加这个新功能的代码,就造成了大量的重复代码,
#所以就可以重新定义个函数用于表示这个新功能
#如下
# def foo():
#     print("I'm foo")
#
#
# def NEW_F(func):
#     print("NEW function")
#     func()
#
# NEW_F(foo)
#我们每次都要将一个函数作为参数传递给NEW_F函数。而且这种方式已经破坏了原有的代码逻辑结构,
# 之前执行业务逻辑时,执行运行bar(),但是现在不得不改成NEW_F(foo)。
#此时就需要装饰器了







#
简单装饰器 # def foo(): # print("I'm foo") # # # def NEW_F(func): # # def wrapper(*args,**keyargs): # print("NEW function") # return func(*args,*keyargs) # return wrapper # # foo = NEW_F(foo) # foo() #函数NEW_F就是装饰器,它把执行真正业务方法的func包裹在函数里面,看起来像foo被 #NEW_F装饰了。在这个例子中,函数进入和退出时 ,被称为一个横切面(Aspect),这种编程方式 # 被称为面向切面的编程(Aspect-Oriented Programming)。 #@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作 # def NEW_F(func): # # def wrapper(*args,**keyargs): # print("NEW function") # return func(*args,*keyargs) # return wrapper # # # @NEW_F #需注意装饰器函数必须先定义再应用 # def foo(): # print("I'm foo") # # # foo() #如上所示,这样我们就可以省去foo = NEW_F(foo)这一句了,直接使用foo()了 #如果我们有其他的类似函数,我们可以继续调用装饰器来修饰函数,而不用重复修改函数或者增加新的封装。 # 带参数的装饰器 # 装饰器还有更大的灵活性,例如带参数的装饰器:在上面的装饰器调用中,比如@NEW_F, # 该装饰器唯一的参数就是执行业务的函数。装饰器的语法允许我们在调用时, # 提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。 def logging_f(level): def decorator(func): def wrapper(*args,**keyargs): if level == "warn": print('出现紧急情况!') return func(*args) return wrapper return decorator @logging_f(level="warn") def foo(): print("I'm foo") foo() #上面的use_logging是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。 # 我们可以将它理解为一个含有参数的闭包。当我 们使用@use_logging(level="warn")调用的时候,Python能够发现这一层的封装, # 并把参数传递到装饰器的环境中。

 


面向对象

对象

# #
class Foo:  # class 类名

    def F1(self, name):  # 定义函数,在类中叫做方法
        print('Hello,world!')
        print(name)
        return '返回值'


# 调用类
# 创建对象
obj = Foo()  # 对象 = 类名()
# 通过对象执行方法
r = obj.F1('chentaicheng')  # 对象.方法()
print(r)
# #

构造方法,self

析构方法

# #
class Foo:

    def __init__(self,name,age,addr):
        self.name = name
        self.age = age
        self.addr = addr

    def F1(self,name):
        print('Hello,world!')
        print(name)
        return '返回值'

    def __del__(self):#析构方法
        print("没有[%s]这个人了"%self.name)

#创建对象,即运行类名()就会自动先执行类中的__init__方法
obj = Foo('chentaicheng',21,'shantou')
print(obj.addr)   #obj.addr即使self.addr
del obj #del会触发析构方法
##

面向对象三大特性:封装、继承、多态

# 多态: 可对不同类的对象使用同样的操作。
# 封装:对外部世界隐藏对象的工作细节。
# 继承:以普通的类为基础建立专门的类对象。

封装:例子:__init__方法,把类(参数,参数……)括号里的参数封装到对象中去。

继承:

# 自己有先执行自己的,没有再从父类中找
# 没有共同父类时,一条道走到黑
# 有共同的一个父类时,从左先执行,走到顶端(未到父类)就不走缩回去

 

#先上一个比较简单的单继承语法。在python3中,基类的构造函数不会被自动调用,需要手动调用,同样的方法也是这样,需要手动调用。
可以使用类名称 + init方法,也可以使用super语法进行调用。在下面这个例子中,子类继承了基类的方法和字段。字段会在基类中初始化。
# class BaseClass: def __init__(self): self.name = 'BaseClass' print('BaseCalss: Constructor called') def getname(self): print('BaseCalss: self name equals ' + self.name) class DerivedClass(BaseClass): def __init__(self): super().__init__() print('DerivedClass: Constructor called') if __name__ == '__main__': class1 = BaseClass() class1.getname() class2 = DerivedClass() class2.getname() # 运行结果: BaseCalss: Constructor called BaseCalss: self name equals BaseClass BaseCalss: Constructor called DerivedClass: Constructor called BaseCalss: self name equals BaseClass
子类也可以overwrite父类的方法,那么父类的方法就不会被调用,除非手动调用:
class BaseClass:
    def __init__(self):
        self.name = 'BaseClass'

        print('BaseCalss: Constructor called')

    def getname(self):
        print('BaseCalss: self name equals ' + self.name)


class DerivedClass(BaseClass):
    def __init__(self):
        super().__init__()

        print('DerivedClass: Constructor called')

    def getname(self):
        print('self.name init value is ' + self.name)

        self.name = 'DerivedClass'

        print('DerivedClass: self name equals ' + self.name)


if __name__ == '__main__':
    class1 = BaseClass()

    class1.getname()

    class2 = DerivedClass()

    class2.getname()
#
#         运行结果:
BaseCalss: Constructor called
BaseCalss: self name equals BaseClass
BaseCalss: Constructor called
DerivedClass: Constructor called
self.name init value is BaseClass
DerivedClass: self name equals DerivedClass
python不仅仅支持单继承,还支持多继承,字段和方法都可以被继承。在多继承super()只能代表继承的第一个父类,所以您在子类的构造函数中,不能单独使用super().__init__(),
那只是表示调用其中一个基类的构造函数。所以用super就不是那么好用了。还是要用会原来的类名 + init方法来调用
class BaseClass1:
    def __init__(self):
        self.name1 = 'BaseClass1_Name1'

        self.name = 'BaseClass1_Name'

        print('BaseCalss1: Constructor called')

    def getname1(self):
        print('BaseCalss1: self name1 equals ' + self.name1)

    def getname(self):
        print('BaseCalss1: getname called, name equal ' + self.name)


class BaseClass2:
    def __init__(self):
        self.name2 = 'BaseClass2_Name2'

        self.name = 'BaseClass2_Name'

        print('BaseClass2: Constructor called')

    def getname2(self):
        print('BaseClass2: self name2 equals ' + self.name2)

    def getname(self):
        print('BaseCalss2: getname called, name equal ' + self.name)


class DerivedClass2(BaseClass1, BaseClass2):
    def __init__(self):
        BaseClass1.__init__(self)

        BaseClass2.__init__(self)

        print('DerivedClass: Constructor called')


if __name__ == '__main__':
    class1 = BaseClass1()

    class1.getname1()

    class2 = BaseClass2()

    class2.getname2()

    class3 = DerivedClass2()

    class3.getname1()

    class3.getname2()

    class3.getname()
#
#         运行结果:
BaseCalss1: Constructor called
BaseCalss1: self name1 equals BaseClass1_Name1
BaseClass2: Constructor called
BaseClass2: self name2 equals BaseClass2_Name2
BaseCalss1: Constructor called
BaseClass2: Constructor called
DerivedClass: Constructor called
BaseCalss1: self name1 equals BaseClass1_Name1
BaseClass2: self name2 equals BaseClass2_Name2
BaseCalss1: getname called, name equal BaseClass2_Name
 
 

我们可以看到,当两个基类有方法重名的时候,python3会按照您继承类的从左到右的顺序查找您调用的方法DerivedClass2(BaseClass1,BaseClass2)。在这个例子中,是先找BaseClass1,然后再找BaseClass2。如果您的代码需要多层继承的话,可以参开多重继承的Diamond Problem问题。

class A1:
    def foo1(self):
        print("Call A1's foo1")


class A2:
    def foo1(self):
        print("Call A2's foo1")

    def foo2(self):
        print("Call A2's foo2")


class B1(A1, A2):
    pass


class B2(A1, A2):
    def foo2(self):
        print("Call B2's foo2")


class C(B1, B2):
    pass


if __name__ == '__main__':
    class1 = C()

    class1.foo1()

    class1.foo2()

#         运行结果:
Call A1's foo1
Call B2's foo2


所以对于python3的多层继承来说,因为都是新式类,总是从左到右,广度优先的方式进行。

多态:

多态(英语:Polymorphism),是指面向对象程序运行时,相同的消息可能会送给多个不同的类之对象,而系统可依据对象所属类,引发对应类的方法,而有不同的行为。
简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作称之。在面向对象程序设计中,多态一般指子类型多态(Subtypepolymorphism)。
上面的定义有点让初学者费解,黄哥用“打开”这个动作来描述面向对象的多态。"打开",可以是打开门,打开窗户,打开书等等。"打开"这个动作,碰到不同的对象门,窗户,书,有不同的行为模式。
这个就是多态。
# 示例一:
class
Door(object): def open(self): print("打开门") class Windows(object): def open(self): print("打开窗户") class Book(object): def open(self): print("打开书") lst = [Door(), Windows(), Book()] for item in lst: item.open()
 
 
# 示例二 一般用继承来说明多态的例子
class
Animal: def __init__(self, name): self.name = name def talk(self): raise NotImplementedError("Subclass must implement abstract method") class Cat(Animal): def talk(self): return 'Meow!' class Dog(Animal): def talk(self): return 'Woof! Woof!' animals = [Cat('Missy'), Cat('Mr. Mistoffelees'), Dog('Lassie')] for animal in animals: print(animal.name + ': ' + animal.talk())
# #python 内置有很多多态的应用
# 同样的 +号 可以用在不同的对象相加,体现(相仿:指相加这个事情)了多态的功能。
# print (1 + 2)
# print ("hello " + 'world')
#
# # len 函数传不同的参数,也体现了多态的功能。
# print (len("python"))
# print (len([2, 4, 5, 7]))
#

 

 


 


 

 

成员:


 

 

字段:静态字段/普通字段
class Foo:

    stati = '静态字段'

    def F1(self):
        general = '普通字段'
        print(general)
        return 'F1返回值'

print(Foo.stati)    #静态字段加载类时自动创建,所以可以直接使用
obj = Foo()
obj.F1()
方法:函数在类中就叫做方法。
普通方法    #由对象调用执行
@staticmethod   #由类调用执行
@calssmethod   #由类调用执行
class Foo:
    @classmethod
    def F1(cls,a1):  #cls必须要的
        print('f1',a1)

    @staticmethod
    def F2(a1):  #参数至少一个
        print(123,a1)

Foo.F1(111)     #由类调用,不需传入参数
Foo.F2(121)     #由类调用,至少传入一个参数
 
 
属性:具有方法的写作形式,具有字段的访问形式,即增删改差
@property  @x.setter  @x.deleter
统计页数
class pager:

    def __init__(self,all_count):
        self.all_count = all_count

    @property
    def all_pager(self):
        a1,a2 = divmod(self.all_count,10)
        if a2 == 0:
            return a1
        else:
            return a1+1

    @all_pager.setter
    def all_pager(self,values):
        print('调用了setter')

    @all_pager.deleter
    def all_pager(self):
        print('调用了deleter')


p = pager(11)       #创建对象
ret = p.all_pager    #对象调用类中的方法,不加property时应该是p.all_paper(),使用了property后调用方法不用加()
#即加了@property后,调用该方法不用需要 对象.方法()而直接 对象.方法
print(ret)

p.all_pager = 111  #类中的all_paper方法使用了@property,则在使用p.all_paper = 时就会调用 类中加了all_paper.setter下面的方法,并且all_paper.setter下面的方法名也必须为all_paper

del p.all_pager

*反射:把字符串反射成内存地址

hasattr()  、  delattr()  、  setattr()  、  getattr()

反射即想到4个内置函数分别为:getattr、hasattr、setattr、delattr  获取成员、检查成员、设置成员、删除成员下面逐一介绍先看例子:

class Foo(object):
 
    def __init__(self):
        self.name = 'abc'
 
    def func(self):
        return 'ok'
 
obj = Foo()
#获取成员
ret = getattr(obj, 'func')#获取的是个对象
r = ret()
print(r)
#检查成员
ret = hasattr(obj,'func')#因为有func方法所以返回True
print(ret)
#设置成员
print(obj.name) #设置之前为:abc
ret = setattr(obj,'name',19)
print(obj.name) #设置之后为:19
#删除成员
print(obj.name) #abc
delattr(obj,'name')
print(obj.name) #报错

对于反射小节:

1.根据字符串的形式导入模块。
2.根据字符串的形式去对象(某个模块)中操作其成员 


 



 








转载于:https://www.cnblogs.com/tcheng/p/5876235.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值