专栏: python轻奢入门系列
作者: 豆破苍琼
【函数】
基本知识
定义
函数可以理解为创建一个具有某种用途的工具。使用def关键字来实现。
调用
def introduce():
name = input("What's your name?")
print("Hello,my name is {}".format(name))
introduce()
注意:
每次调用函数时,函数都会从头开始执行,当这个函数中的代码执行完毕后,意味着调用的结束。当然如果函数执行到return处也会自行结束。
函数的参数
定义函数:
当定义函数时,小括号中的参数,是用来接收数据的,我们称之为"形参"。
调用函数:
当调用函数时小括号中的参数,是用来传递给函数参数的,我们称之为"实参"。
调用函数:
位置参数
位置参数就是咱们目前接触的传参方式,定义函数时设置两个形参,那么在函数调用时候就需要传入两个实参,如果传入数量不相同则会报错。
# 位置参数
def introduce(name):
print("Hello,my name is {}".format(name))
def ask():
name = input("What's your name?")
while len(name)==0:
name = input("What's your name?")
introduce(name)
ask()
关键字参数
关键字参数为位置参数类似,不过在调用函数时候进行传参时有一定的区别。
def add(a,b):
print("{} + {} = {}".format(a,b,a+b))
add(a=2,b=4)
不定长位置参数
这个不定长位置参数,只需要为函数设置一个不定长的位置参数,就可以接受多个值。设置方式是一个*号加上一个参数的名称,参数名称任意。
def playgame(*game):
print(game)
playgame('绝地求生','王者荣耀','地下城')
def playgame(*game,xGame='地下城2'):
for i in game:
print(i)
print(xGame)
playgame('绝地求生','王者荣耀','地下城')
不定长关键字参数
不定长关键字参数与不定长位置参数类似,同样都是设置一个参数就可以接收多个数据。但是在写法上存在一定的区别。
观察函数的输出就能够发现传入的参数以关键字参数的方式进行传值的。调用函数运行之后,输出的结果是一个字典。
一个星号的形参接收的数据之后是元组数据类型,两个星号的形参接收数据之后的数据类型是字典类型。
def playgame(**game):
print("以不定长关键字传值方式:")
for i in game.values():
print(i)
playgame(QQ游戏='王者荣耀',微信游戏='跳一跳')
混合使用多方式参数
其实就是上面几种方式的组合。也没啥大不了的。
def sayHello(n1,*args,nx1='xb',nx2='xh',**kwargs):
print('混合使用多方式参数:')
print(n1,args,nx1,nx2,kwargs)
sayHello(1,2,3,4,nx1=2,mm=22,nn='a')
函数类型
- 无参数、无返回值
- 无参数,有返回值
- 有参数,无返回值
- 有参数,有返回值
- 一个参数返回多个值
【面向对象】
面向对象和面向过程
面向对象
面向对象可以将整个任务封装成一个大的类,在这个类里面详细的分解每个步骤,我们只需要执行类就可以完成相应的任务。
面向过程
核心是过程,过程是解决问题的步骤,就好比一个流水线,是一种机械式的思维方式,优点是将复杂的问题流程化,进而简单化。缺点就是难以扩展。
定义类与方法
类是由三部分构成的。类名,类的属性,类的方法。
类的属性,可以在类的外面和里面对其进行赋值。
类中的魔法方法
魔法方法是指内部已经包含的,被双下划线所包围的方法,这些方法在进行特定的操作时候被自动调用。
- __new__至少有一个参数cls,代表要实例化的类,此参数在实例化时由python解释器自动提供。它必须要有返回值,返回实例化出来的实例。
- __init__方法就是在原有材料的基础上,加工,初始化商品的过程,而__new__方法就是前期的原材料的购买环节,return就是把原材料返回给自己本身,从而进行下一步操作。
- __str__方法用来显示信息,此方法需要返回一个数据,并且只有一个self参数,当在类的外部print(实例对象名)则打印这个数据。
- __del__方法是对象删除时候,默认调用的一种方式。
class Hero(object):
"""
定义了一个英雄类,可以实施攻击和移动
"""
def __init__(self,name,skill,hp,atk,armor):
# 英雄名称
self.name = name
# 英雄技能
self.skill = skill
# 生命值
self.hp = hp
# 攻击力
self.atk = atk
# 护甲值
self.armor = armor
def __new__(cls):
print(id(cls))
def __del__(self):
print("__del__ 方法被调用")
print("%s 被 GM 干掉了..."%self.name)
def move(self):
print("%s 正在前往事发地点..."% self.name)
def arrack(self):
print("发出了一招强力的%s..."%self.skill)
def __str__(self):
"""
魔法方法,用来信息的显示
"""
return "英雄 <%s> 数据:生命值 %d ,攻击力 %d , 护甲值 %d"%(self.name,self.hp,self.atk,self.armor)
print(id(Hero))
hero = Hero()
类方法与静态方法
类方法
在类方法中,可以通过@classmethod装饰器定义,其中方法的参数是cls,代表调用这个方法的类对象本身。
类方法可以被类对象和实例对象调用,而实例方法只能被实例对象调用。
静态方法
静态方法与类方法相似。静态方法也需要装饰器来进行装饰,而这个装饰器就是@staticmethod。经过staticmethod装饰的函数没有self和cls这两个参数。
一般静态方法主要用来存放逻辑性的代码,静态方法内部的操作一般不会涉及到类中的属性和实例方法的操作。
import time
class Student(object):
currentTime = 0
@staticmethod
def showTime():
return time.strftime("%H:%M:%S",time.localtime())
@classmethod
def getCurrentTime(cls):
cls.currentTime = time.localtime()
return cls.currentTime
def __str__(self):
self.getCurrentTime()
return time.strftime("%H:%M:%S",self.currentTime)
#Student.getCurrentTime()
std = Student()
std.getCurrentTime()
print(std)
私有属性和方法
只需要在属性名和方法名前面加上两个下划线__,那么这个属性和方法就会变成私有的。其中,有三点需要注意:
1、类的私有属性和私有方法都不能通过对象直接访问,但是可以在本类内部访问。
2、类的私有属性和私有方法,都不会被子类继承,子类也无法访问。
3、私有属性和私有方法通常处理类内部的事情,不通过对象处理,起到安全作用。
class Hero():
"""
定义了一个英雄类,可以实施攻击和移动
"""
__weight = "180 kg" # 私有类属性
def __init__(self,name,skill,hp,atk,armor):
# 英雄名称
self.name = name
# 英雄技能
self.skill = skill
# 生命值
self.hp = hp
# 攻击力
self.atk = atk
# 私有实例属性
self.__age = 35
# 护甲值
self.armor = armor
def __del__(self):
print("__del__ 方法被调用")
print("%s 被 GM 干掉了..."%self.name)
def move(self):
print("%s 正在前往事发地点..."% self.name)
def arrack(self):
print("发出了一招强力的%s..."%self.skill)
def __str__(self):
"""
魔法方法,用来信息的显示
"""
return "英雄 <%s> 数据:生命值 %d ,攻击力 %d , 护甲值 %d"%(self.name,self.hp,self.atk,self.armor)
def __takeKongFu(self):
print("<%s> 长枪一出! 什么花在手!..." % self.name)
# 访问私有属性和方法
def visit(self):
print(self.__weight)
print(self.__age)
self.__takeKongFu()
# 修改私有属性和方法
def amend(self,weight,age):
self.__weight = weight
self.__age = age
hero = Hero("菊花","菊花茶",100,2200,4000)
hero.arrack()
hero.visit()
hero.amend("100 kg",60)
hero.visit()
print(hero)
面向对象的三大特性
封装
面向对象编程一个重要特点就是数据的封装。主要有以下优点:
1、我们可以通过函数来访问这些数据
2、可以给类增加新的方法
"""
面向对象的三大特性
"""
class Student(object):
def __init__(self,name,score):
self.name = name
self.score = score
def print_score(self):
print('%s : %s'%(self.name,self.score))
def get_score(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
bboy = Student('楚怀王',"96")
bboy.print_score()
继承
使用继承的原因:
1、减少代码的冗余
2、功能的升级和扩展
单层继承、多层继承、多继承
class Animal:
def eat(self):
print("Eat...")
def drink(self):
print("Drink...")
class Dog(Animal):
def bark(self):
print("Barking...")
class HSQ(Dog):
def __init__(self,name):
self.__name = name
def __str__(self):
return "HSQ's name is %s"%(self.__name)
hsq = HSQ("大壮")
print(hsq)
hsq.eat()
hsq.bark()
# 查看类的继承链
HSQ.__mro__
class Father():
def talk(self):
print("哔哔哔")
class Mother():
def smart(self):
print("嘟嘟嘟")
class Child(Father,Mother):
pass
child = Child()
child.talk()
child.smart()
调用被重写的方法、重写__init__
子类重写了父类的方法,但是仍然想执行父类中的方法,可以选择以下几种方式:
- 父类名.方法名(self)
- super(类名,self).方法名()
- super().方法名 当前类的下一个类的方法
重写__init__可以定义不同的属性。
class Animal:
def eat(self):
print("Eat...")
def drink(self):
print("Drink...")
class Dog(Animal):
def __init__(self):
self.name ="哈士奇"
self.age = 3
self.color = "蛋黄色"
def bark(self):
print("Barking...")
class HSQ(Dog):
def __init__(self,name):
super(HSQ,self).__init__()
self.__name = name
self.color = "黑色"
def bark(self):
super(HSQ,self).bark()
print("Wa... i\'m special dog!'")
def __str__(self):
return "HSQ's name is %s,age is %d,color is %s"%(self.__name,self.age,self.color)
hsq = HSQ("大壮")
print(hsq)
hsq.eat()
hsq.bark()
多态
多态指一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
在继承关系中,如果实例的数据类型是某个子类,那它的数据类型也可以被看作是父类,反过来就不行。
判断方式用isinstance(实例,类名)对其进行判断。
【参考】
1.https://www.runoob.com/w3cnote/python-func-decorators.html