Python 编程要点-- 变量和函数传参

来源:互联网 发布:颀乎其 编辑:程序博客网 时间:2024/06/05 19:24

Python 变量和函数传参

类变量和实例变量

通过下面的例子说明类变量和实例变量的区别与访问权限说明:当类变量和成员变量前面是__开头时,一种python的约定为不能在外部访问该类变量或者成员变量,因为Python解释器会把该变量前面加上 _Foo(Foo为类名)当做成员变量的名称,但是我们按照这样的方式( _Foo__cls_name )还是可以访问

class Foo(object):                                                                                                                                                 cls_name = "Python"    cls_dict = {"age":10}    _cls_name = "C++"    _cls_dict = {"age":20}    __cls_name = "Java"    __cls_dict = {"age":30}    def __init__(self):        self.sel_name = "C"         self.sel_dict = {"age":40}        self._sel_name = "Perl"        self._sel_dict = {"age":50}        self.__sel_name = "C#"        self.__sel_dict = {"age":60}        print Foo.cls_name        print Foo.cls_dict        print Foo._cls_name        print Foo._cls_dict        print Foo.__cls_name        print Foo.__cls_dict        print self.cls_name        print self.cls_dict        print self._cls_name        print self._cls_dict        print self.__cls_name        print self.__cls_dict        #Error:  Class 'Foo' has no '__sel_dict' member; maybe '_sel_dict'        #print Foo.sel_name         #print Foo.sel_dict        #print Foo._sel_name        #print Foo._sel_dict        #print Foo.__sel_name        #print Foo.__sel_dict        print self.sel_name        print self.sel_dict        print self._sel_name        print self._sel_dictf = Foo()print Foo.cls_nameprint Foo.cls_dictprint Foo._cls_nameprint Foo._cls_dict#Error :type object 'Foo' has no attribute '__cls_name'#print Foo.__cls_name#print Foo.__cls_dictprint f.cls_nameprint f.cls_dictprint f._cls_nameprint f._cls_dict#Error: 'Foo' object has no attribute '__cls_name'#print f.__cls_name#print f.__cls_dictprint Foo._Foo__cls_nameprint Foo._Foo__cls_dictprint f._Foo__cls_nameprint f._Foo__cls_nameprint f.sel_nameprint f.sel_dictprint f._sel_nameprint f._sel_dict#Error: 'Foo' object has no attribute '__sel_name'#print f.__sel_name#print f.__sel_dictprint f._Foo__sel_nameprint f._Foo__sel_dict

尝试修改类变量和成员变量:
结论是当修改了类变量后,后面申明的实例访问的也是改变后的类变量,因为类变量在内存中只会存在一份。然而实例变量作用域为单个实例,它表明每一个实例的变量内存空间不一样。

class Foo(object):                                                                                                                                                 cls_name = "Python"    cls_dict = {"age":10}    _cls_name = "C++"    _cls_dict = {"age":20}    __cls_name = "Java"    __cls_dict = {"age":30}    def __init__(self):        self.sel_name = "C"         self.sel_dict = {"age":40}        self._sel_name = "Perl"        self._sel_dict = {"age":50}        self.__sel_name = "C#"        self.__sel_dict = {"age":60}    def cls_func(self, keys):        Foo.cls_name = "Python_change"        Foo.cls_dict[keys] = 100         Foo._cls_name = "C++_change"        Foo._cls_dict[keys] = 200         Foo.__cls_name = "Java_change"        Foo.__cls_dict[keys] = 300     def sel_func(self, keys):        self.sel_name = "Python_sel_change"        self.sel_dict[keys] = 1000        self._sel_name = "C++_sel_change"        self._sel_dict[keys] = 2000        self.__sel_name = "Java_sel_change"        self.__sel_dict[keys] = 3000f = Foo()f.cls_func("age1")print Foo.cls_nameprint Foo.cls_dictprint Foo._cls_nameprint Foo._cls_dict#Error:type object 'Foo' has no attribute '__cls_name'#print Foo.__cls_name#print Foo.__cls_dictprint f.cls_nameprint f.cls_dictprint f._cls_nameprint f._cls_dict#Error: 'Foo' object has no attribute '__cls_name'#print f.__cls_name#print f.__cls_dictf2 = Foo()f2.cls_func("age2")print f2.cls_nameprint f2.cls_dictprint f2._cls_nameprint f2._cls_dictprint f2._Foo__cls_nameprint f2._Foo__cls_dictf.sel_func("age1")print f.sel_nameprint f.sel_dictprint f._sel_nameprint f._sel_dictprint f._Foo__sel_nameprint f._Foo__sel_dictf2.sel_func("age2")print f2.sel_nameprint f2.sel_dictprint f2._sel_nameprint f2._sel_dictprint f2._Foo__sel_nameprint f2._Foo__sel_dict>>Python_change{'age': 10, 'age1': 100}C++_change{'age': 20, 'age1': 200}Java_change{'age': 30, 'age1': 300}Python_change{'age': 10, 'age1': 100}C++_change{'age': 20, 'age1': 200}Java_change{'age': 30, 'age1': 300}Python_change{'age': 10, 'age2': 100, 'age1': 100}C++_change{'age': 20, 'age2': 200, 'age1': 200}Java_change{'age': 30, 'age2': 300, 'age1': 300}Python_sel_change{'age': 40, 'age1': 1000}C++_sel_change{'age': 50, 'age1': 2000}Java_sel_change{'age': 60, 'age1': 3000}Python_sel_change{'age': 40, 'age2': 1000}C++_sel_change{'age': 50, 'age2': 2000}Java_sel_change{'age': 60, 'age2': 3000}

当继承父类的类成员变量时,子类继承来可变对象的在子类修改也会影响到父类,因此可以将类成员变量看成是类的父类以及其子类独有的存在,就像类的全局变量:

class A():                                                                                                                                                         cls_name = "Python"    cls_list = [1,2]class B(A):    def cls_func(self, age):        B.cls_list.append(age)b = B() print b.cls_nameprint b.cls_listb.cls_func(3)print b.cls_listprint A.cls_lista = A() print a.cls_list>>Python[1, 2][1, 2, 3][1, 2, 3][1, 2, 3]

函数参数传递

Python 里面的对象分为可变对象和不可变对象
可变对象:list,dict。
不可变对象:int,string,float,tuple。
当函数定义时如果传递的是不可变对象就是值传递,比如:

def func(a):    a = a + 10    print ab = 11func(b)print b>>2111

以上例子说明b并未被函数修改,说明传递的数据为不可变对象的时候是值传递。
当传递的是可变对象时,就是传递的应用,比如:

def func(list_a):    list_a.append(10)    print list_al = [1,2,3]func(l)print l>>[1,2,3,10][1,2,3,10]

以上例子说明当传递一个可变对象list,并且在函数体内部修改了该可变对象,那么该对象会影响到外部传递的那个list对象。

python中应该避免将可变对象作为函数参数的默认值

在python中函数也是对象,它的参数就是它的成员变量,当你把可变对象当做函数参数的默认值时会导致的问题就是如果你在函数体中有增删查改这个可变对象的代码,那么当你多次调用时会发现这个可变对象是连续变化的。如:

def func(ages=[7, 8], age=None):    ages.append(age)    return ab = func(age=10)c = func(age=11)d = func(age=12)print bprint cprint d>>[7, 8, 10][7, 8, 10, 11][7, 8, 10, 11, 12]

你会发现这个函数失去了你想要达到的目的,产生这个现象的原因是func函数的可变对象a只会有一个定义,每次调用它时都会使用这个对象a的引用,那么多次调用该函数就出现了上面的结果。
修改:

def func(a=None, age=None):                                                                                                                                        if a is None:        a = [7, 8]    a.append(age)    return ab = func(age=10)c = func(age=11)d = func(age=12)print bprint cprint d>>[7, 8, 10][7, 8, 11][7, 8, 12]
原创粉丝点击