python的函数属性

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变量来进行限定自定义类型的对象只能绑定某些属性。

通过@propertygettersetter属性保护age, name

 
15756588-595dec68c3f9c145.png
image.png

 

通过__slots__限定Person对象只能绑定_name, _age, _gender属性

 
15756588-9b2b0376d5cf7733.png
 

 


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()
class ConstrainedList (list): """Constrains the list class so it offers only the following primitive array API: - `lst[i]` for getting and setting a value at an *existing, positive* index `i` - `len(lst)` to obtain the number of slots - `lst.append(None)` to grow the list by *one slot at a time* - `del lst[len(lst)-1]` to delete the last slot in a list All other operations will result in an exception being raised. """ def __init__(self, *args): super().__init__(*args) def append(self, value): if value is not None: raise ValueError('Can only append None to constrained list!') super().append(value) def __getitem__(self, idx): if idx < 0 or idx >= len(self): raise ValueError('Can only use positive, valid indexes on constrained lists!') return super().__getitem__(idx) def __setitem__(self, idx, value): if idx < 0 or idx >= len(self): raise ValueError('Can only use positive, valid indexes on constrained lists!') super().__setitem__(idx, value) def __delitem__(self, idx): if idx != len(self)-1: raise ValueError('Can only delete last item in constrained list!') super().__delitem__(idx) def __getattribute__(self, name): if name in ('insert', 'pop', 'remove', 'min', 'max', 'index', 'count', 'clear', 'copy', 'extend'): raise AttributeError('Method "' + name + '" not supported on constrained list!') else: return super().__getattribute__(name) # __getattribute__ isn't called for special methods, so the following are needed def __add__(self, value): raise AttributeError('Constrained lists do not support `+`!') def __contains__(self, value): raise AttributeError('Constrained lists do not support `in`!') def __eq__(self, value): raise AttributeError('Constrained lists do not support `==`!') def __iter__(self): raise AttributeError('Constrained lists do not support iteration!') def __str__(self): raise AttributeError('Constrained lists do not support stringification!') def __repr__(self): raise AttributeError('Constrained lists do not support stringification!') # for testing only! (don't use this in your ArrayList implementation) def _as_list(self): return list(super().__iter__())
最新发布
02-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值