1. 函数的参数
在Python中,函数的参数可以有默认值,也支持使用可变参数,所以Python并不需要像其他语言一样支持函数的重载,因为我们在定义一个函数的时候可以让它有多种不同的使用方式。
# 在参数名前面的*表示args是一个可变参数
# 即在调用add函数时可以传入0个或多个参数
def add(*args):
total = 0
for val in args:
total += val
return total
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
print(add(1, 3, 5, 7, 9))
2. 变量作用域
def foo():
b = 'hello' # 函数中的局部变量(local variable)
def bar(): # Python中可以在函数内部再定义函数
c = True # 局部作用域
nonlocal b
print(a)
print(b)
print(c)
bar()
# print(c) # NameError: name 'c' is not defined
if __name__ == '__main__':
a = 100 # 全局变量(global variable)
# print(b) # NameError: name 'b' is not defined
foo()
'''
改变 全局变量(global variable)a 的值,需要使用 global关键字
改变 局部变量(local variable)b 的值,需要使用 nonlocal 关键字
'''
在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被垃圾回收。事实上,减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措。
def main():
# Todo: Add your code here
pass
if __name__ == '__main__':
main()
3. 面向对象
class Person(object):
# 限定Person对象只能绑定_name, _age和_gender属性
__slots__ = ('_name', '_age', '_gender')
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
if self._age <= 16:
print('%s正在玩飞行棋.' % self._name)
else:
print('%s正在玩斗地主.' % self._name)
def main():
person = Person('王大锤', 22)
person.play()
person._gender = '男'
print(person._age)
# AttributeError: 'Person' object has no attribute '_is_gay'
# person._is_gay = True
if __name__ == '__main__':
main()
3.1 @property装饰器
将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,考虑使用@property包装器来包装getter和setter方法,属性的getter(访问器)和setter(修改器)方法进行对应的操作,使得对属性的访问既安全又方便。
class Circle(object):
def __init__(self, radius):
self.radius=radius
def getRadius(self):
return self.radius
def setRadius(self, value):
if not isinstance(value,(int, float)):
raise ValueError(' wrong type.')
self.radius=float(value)
def getArea(self):
return self. radius ** 2 * 3.14
# 通过property自动调用属性
R = property(getRadius, setRadius)
if __name__ == '__main__':
c = Circle(3)
print(c.radius)
c.radius = 9
print(c.radius)
3.2 slots魔法
通过在类中定义slots变量来进行限定自定义类型的对象只能绑定某些属性。
通过
@property
的getter
和setter
属性保护age, name
image.png
通过
__slots__
限定Person
对象只能绑定_name, _age, _gender
属性![]()
4. 静态类
网上说的比较多的是,静态类不需要实例化就可以直接调用内部的方法。但是什么时候用这个静态类说的却不是很详细,在这里给出了一个很好的使用范例:
在计算三角形周长时,传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。
from math import sqrt
class Triangle(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
@staticmethod
def is_valid(a, b, c):
return a + b > c and b + c > a and a + c > b
def perimeter(self):
return self._a + self._b + self._c
def area(self):
half = self.perimeter() / 2
return sqrt(half * (half - self._a) *
(half - self._b) * (half - self._c))
def main():
a, b, c = 3, 4, 5
# 静态方法和类方法都是通过给类发消息来调用的
if Triangle.is_valid(a, b, c):
t = Triangle(a, b, c)
print(t.perimeter())
# 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
# print(Triangle.perimeter(t))
print(t.area())
# print(Triangle.area(t))
else:
print('无法构成三角形.')
if __name__ == '__main__':
main()