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)这个函数



  • 相关阅读:
    (4.25)Sqlserver中 登录用户只能看到自己拥有权限的库
    【查阅】mysql配置文件/参数文件重要参数笔录(my.cnf)
    【监控笔记】【2.5】DML(CDC)、DDL(DDL触发器)跟踪数据更改,数据库审计
    SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑
    【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况
    【监控笔记】【2.3】扩展事件——慢查询SQL(执行超过3S的SQL)
    【监控笔记】【2.2】扩展事件——死锁监控
    最小配置启动SQL SERVER,更改SQL Server最大内存大小导致不能启动的解决方法
    【监控笔记】【2.1】扩展事件
    【扩展事件】跟踪超过3秒的SQL
  • 原文地址:https://www.cnblogs.com/yoyowin/p/13502464.html
Copyright © 2011-2022 走看看