zoukankan      html  css  js  c++  java
  • Python类的私有属性与私有方法的使用

    xx: 公有变量
    _x: 单前置下划线,私有化属性或方法,from somemodule import 禁止导入,类对象和子类可以访问【另解:前置单下划线,又称口头私有变量,私有化属性或方法的一种,一般来讲,变量名_xx被看作是“私有 的”,在模块或类外不可以使用。当变量是私有的时候,用_xx 来表示变量是很好的习惯。类对象和子类可以访问,这并不能完全做到真正的私有,只是约定俗成的而已,这样写表示不希望这个变量在外部被直接调用】
    __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)【__xx:前置双下划线,私有化属性或方法,只有内部可以访问,外部不能访问。】
    __xx__:双前后下划线,用户名字空间的魔法对象或属性。例如:init , __ 不要自己发明这样的名字【__xx__:以双下划线开头,并且以双下划线结尾的,是特殊变量(这就是在python中强大的魔法方法),特殊变量是可以直接访问的,对于普通的变量应当避免这种命名风格。】
    xx
    :单后置下划线,用于避免与Python关键词的冲突
    通过name mangling(名字重整(目的就是以防子类意外重写基类的方法或者属性)如:_Class__object)机制就可以访问private了。

    #coding=utf-8
    
    class Person(object):
        def __init__(self, name, age, taste):
            self.name = name
            self._age = age 
            self.__taste = taste
    
        def showperson(self):
            print(self.name)
            print(self._age)
            print(self.__taste)
    
        def dowork(self):
            self._work()
            self.__away()
    
    
        def _work(self):
            print('my _work')
    
        def __away(self):
            print('my __away')
    
    class Student(Person):
        def construction(self, name, age, taste):
            self.name = name
            self._age = age 
            self.__taste = taste
    
        def showstudent(self):
            print(self.name)
            print(self._age)
            print(self.__taste)
    
        @staticmethod
        def testbug():
            _Bug.showbug()
    
    # 模块内可以访问,当from  cur_module import *时,不导入
    class _Bug(object):
        @staticmethod
        def showbug():
            print("showbug")
    
    s1 = Student('jack', 25, 'football')
    s1.showperson()
    print('*'*20)
    
    # 无法访问__taste,导致报错
    # s1.showstudent() 
    s1.construction('rose', 30, 'basketball')
    s1.showperson()
    print('*'*20)
    
    s1.showstudent()
    print('*'*20)
    
    Student.testbug()

    ----------------------------------------------讲解----------------------------------------------------------------------------------------

    1.Python中属性:类属性 ,实例属性,私有属性的使用

    在Python中的属性分为:类属性和对象(实例)属性:

    1.类属性就是属于类所有,可以直接用类名.属性名直接调用,类的属性在内存中只有一份。实例属性就是在__init__()方法中初始化的属性;
    2.实例属性属于类的对象所有,可以用对象名.属性名的形式进行调用,但是不能用类名.属性名进行调用 。因为实例属性只有在实例创建时,才会初始化创建。

    #1.类属性和实例的属性的调用关系
    class Person:
        country ="china"  #类属性
        def __init__(self,name,age):
            sex =""   #这不是实例属性,只是变量而已,用对象名.sex调不出来。
            self.name = name #实例属性
            self.age = age
    #创建对象
    print(Person.country) 
    #print(Person.age) 出错,AttributeError: type object 'Person' has no attribute 'age'
    p1 = Person("tom",12)
    print(p1.country,p1.age,p1.name,p1)
    
    ----------结果如下------------------------------------------------------------------------
    china
    china 12 tom
    ----------------------------------------------------------------------------------------
    
    #2.修改类属性和实例属性:类属性只能通过类名.属性才可以修改
    class Person:
        country ="china"  #类属性
        def __init__(self,name,age):
            sex =""   #这不是实例属性,只是变量而已,用对象名.sex调不出来。
            self.name = name #实例属性
            self.age = age
     
    -------创建对象-------------------------------------------------------------------------
    p1.country = "america"
    print(p1.country) #通过实例去修改属性,实例的属性修改了:america
    print(Person.country)#但是类的属性还是没有修改:china
     
    Person.country = "japan" #只有用类名.属性名才能修改类的属性值。
    p2= Person("jack",11)
    print("p1.country:",p1.country) 
    print("p2.country",p2.country)
    print("Person.country",Person.country)
    ------结果如下-----------------------------------------------------------------------------
    america
    china
    p1.country: america
    p2.country japan
    Person.country japan

    实际开发中为了程序的安全,关于类的属性都会封装起来,Python中为了更好的保存属性安全,即不能随意修改。一般属性的处理方式为:1.将属性定义为私有属性。2.添加一个可以调用的方法,供调用。

    3.Python中用__两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问

    class Person1(object):
        country ='china' #类属性
        __language ="Chinese" #私有类属性也不能直接外部调用
        def __init__(self,name,age):
            self.name = name
            self.__age = age  #使用__下划线表示私有属性,对象不能直接调用,要通过方法调调用
     
        def getAge(self):
            return self.__age
     
        def setAge(self,age):
            if age >100 or age <0:
                print("age is not true")
            else :
                self.__age = age
     
        def __str__(self):
            info = "name :"+self.name +",age(保密):"+str(self.__age)  #注意这里不是self.age
            return info
     
    #------创建对象,调用方法,属性测试-------------------------------------------------------
    stu1 =  Person1("tom",18)
    print("修改前的结果:",stu1.__str__())
    stu1.name="tom_2"  #修改stu1的name属性
    print("修改name后的结果:",stu1.__str__())
    #print(stu1.__age)  #直接调用私有属性__age报错,'Person1' object has no attribute '__age'
     
    print("打印私有age内存地址:",id(stu1.getAge()))
    stu1.__age = 19  #如果这样赋值的话,不会报错,因为系统找不到这个变量,直接新建了一个。但是实际没有修改对象的属性值
    print(stu1.__age) #有值,但是没有 实际修改stu1对象的age属性值
    print("打印stu1.__age的内存地:",id(stu1.__age)) #两个内存地址值不一样。
    print("错误修改age后的值",stu1.__str__())  #实际值没有变
     
    stu1.setAge(22) #只有调用才可以修改age的值
    print("正确修改age后的值",stu1.__str__())
     
    '''执行结果如下:
    修改前的结果: name :tom,age(保密):18
    修改name后的结果: name :tom_2,age(保密):18
    打印私有age内存地址: 1388146224
    19
    打印stu1.__age的内存地: 1388146256
    错误修改age后的值 name :tom_2,age(保密):18
    正确修改age后的值 name :tom_2,age(保密):22
    '''

    2.私有方法,类方法,静态方法的使用

    1.私有方法:以 __两个下划线开头,声明该方法为私有方法,只能在类的内部调用 (类内部别的方法可以调用他),不能在类地外部调用。

    lass Person5:
     
        def __p(self):
            print("这是私有属性") #内部函数也同样可以任意之间互相调用
        def p1(self):
            print("这是p1不是私有方法")
        def p2(self):
            print("这是p2,可以调用p1,也可以调用私有方法__p")
            self.p1()
            self.__p()
    #创建对象
    c1 = Person5()
    c1.p1()
    c1.p2()
    #c1.__p() #不能直接私有函数。报错。注意区分系统自带的函数如__str__,外部可以直接调用的。
     
    '''结果如下:
    这是p1不是私有方法
    这是p2,可以调用p1,也可以调用私有方法__p
    这是p1不是私有方法
    这是私有属性
    '''

    2.类方法的使用:是类所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,也可以有别的参数。但是第一个必须是类对象,类似类中的def定义的普通方法第一个参数要是self一样的道理

    class People(object):
        country = 'china'
     
        #类方法,用classmethod来进行修饰,跟普通的方法区别就是可以直接通过类名.方法名的方式调用
        @classmethod
        def getCountry(cls):
            return cls.country
        @classmethod
        def sum(cls,a,b):
            return a+b        
     
    p = People()
    print (p.getCountry())  #可以用过实例对象引用
    print (People.getCountry() )   #可以通过类名.方法名的形式调用
    print(p.sum(10,11))  
    print(People.sum(10,11))
    ====================================================================================
    china
    china
    21
    21
    3.静态方法:需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数 
    
    class People(object):
        country = 'china'
     
        @staticmethod
        #静态方法,不用定义参数
        def getCountry():
            return People.country
     
     
    print (People.getCountry())

    3.方法的使用注意要点
    注意python中不支持方法的重载:即方法名相同,参数类型(参数个数不同)不同的函数,python中 不支持。

    def p():
        print("dd")
    def p(a,b):
        print("dd")
     
    def p(a):
        print("dd")
    p()#报错,因为python中不需要定义参数的类型。如果有多个重载的函数,则python默认只能使用最后一个有效。
    所以只能调用P(a)这个函数



  • 相关阅读:
    Struts2+Spring3+Mybatis3开发环境搭建
    spring+struts2+mybatis
    【LeetCode】Populating Next Right Pointers in Each Node
    【LeetCode】Remove Duplicates from Sorted Array
    【LeetCode】Remove Duplicates from Sorted Array II
    【LeetCode】Binary Tree Inorder Traversal
    【LeetCode】Merge Two Sorted Lists
    【LeetCode】Reverse Integer
    【LeetCode】Same Tree
    【LeetCode】Maximum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/yoyowin/p/13502464.html
Copyright © 2011-2022 走看看