一、私有权限

1.封装的意义:

  • 将属性和方法放到一起做为一个整体,然后通过实例化对象来处理
  • 隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了
  • 对类的属性和方法增加访问权限控制

2.私有权限:在属性名和方法名 前面加上两个下划线 __

  • 类的私有属性和私有方法,都不能通过对象直接访问,但是可以在本类内部访问
  • 类的私有属性和私有方法,都不会被子类继承,子类也无法访问;
  • 私有属性和私有方法往往用来处理类的内部事情,不通过对象处理,起到安全作用
#创建人类
class Person():
    #实例方法
    def eat(self):
        print("民以食为天,人活着不吃好吃的会很难受")
    #私有方法
    def __sport(self):
        print("热爱生活,热爱运动!")

#实例化对象
p=Person()
#实例化方法,获取不到sport方法
p.eat()

二、私有属性和私有方法

1.私有方法

#创建人类
class Person():
    #实例方法
    def eat(self):
        print("民以食为天,人活着不吃好吃的会很难受")
    #私有方法
    def __sport(self):
        print("热爱生活,热爱运动!")

#实例化对象
p=Person()
#实例化方法,获取不到sport方法
p.eat()

2.私有属性

#创建人类
class Person():
    def __init__(self):
        #实例属性
        self.name="刘耀文"
        #私有属性
        self.__age=16
    #实例方法
    def eat(self):
        print("民以食为天,人活着不吃好吃的会很难受")
    #私有方法
    def __sport(self):
        print("热爱生活,热爱运动!")

#实例化对象
p=Person()
#实例化方法,获取不到sport方法
p.eat()
#实例化属性,获取不到age属性
print(p.name)

3.类部调用私有属性和私有方法

  • 通常会定义get_xxx()方法和set_xxx()方法来获取和修改私有属性值
  • get_xxx()方法-->返回私有属性的值
  • set_xxx()方法-->接收参数,修改私有属性的值

①调用私有属性

#创建人类
class Person():
    def __init__(self):
        #实例属性
        self.name="刘耀文"
        #私有属性
        self.__age=16
    #实例方法
    def eat(self):
        print("民以食为天,人活着不吃好吃的会很难受")
    #私有方法
    def __sport(self):
        print("热爱生活,热爱运动!")
    #设置私有属性值,方法名称不重要,一般用set_xxx
    def set_money(self,m):
        self.__money=m
    #获取私有属性值,方法名称不重要,一般用get_xxx
    def get_money(self):
        return self.__money

#实例化对象
p=Person()
#实例化方法,获取不到sport方法
p.eat()
#实例化属性,获取不到age属性
print(p.name)
#设置私有属性值
p.set_money(20)
#获取私有属性值
print(p.get_money())

②调用私有方法

#创建人类
class Person():
    def __init__(self):
        #实例属性
        self.name="刘耀文"
        #私有属性
        self.__age=16
    #实例方法
    def eat(self):
        print("民以食为天,人活着不吃好吃的会很难受")
    #私有方法
    def __sport(self):
        print("热爱生活,热爱运动!")
    #获取私有方法
    def get_sport(self):
        return self.__sport()

#实例化对象
p=Person()
#实例化方法,获取不到sport方法
p.eat()
#实例化属性,获取不到age属性
print(p.name)
#获取私有化方法
p.get_sport()

③总结:

  • 私有属性,可以在类内部通过self调用,但不能通过对象直接访问
  • 私有方法,可以在类内部通过self调用,但不能通过对象直接访问
  • 子类不能继承父类中的私有权限的属性和方法
  • Python中没有像C++中public、private、protected这些关键字来区别公有属性和私有属性。
  • Python是以命名方式来区分,如果在属性和方法名前面加了2个下划线__,则表明该属性和方法是私有权限,否则为公有权限

三、类属性和实例属性

1.定义:

  • 类属性就是类拥有的属性,被所有类的实例对象共有,在内存中只存在一个副本。对于公有的类属性,可以直接通过类或者实例对象访问私有类属性不能通过类名和实例对象访问
  • 实例属性就是通过self定义的属性,即实例对象属性

2.类属性

#创建人类
class Person(object):
    #公有的类属性
    name="邓紫棋"
    #私有的类属性
    __age=18

#类属性通过实例化对象调用
p=Person()
print(p.name)
#类属性通过类名直接调用
print(Person.name)

3.实例对象修改类属性

  • 对象修改属性值,只对本对象有效果,对别的对象没有影响
#创建人类
class Person(object):
    # 公有的类属性
    name="邓紫棋"
    #私有的类属性
    __age=18
    # 初始化方法
    def __init__(self):
        #实例属性
        self.name = "刘耀文"

#类属性通过类名直接调用
print(Person.name)
#实例属性会屏蔽掉同名的类属性,只输出实例属性
p=Person()
print(p.name)
#修改属性值
p.name="宋亚轩"
print(p.name)
#对象修改属性值,只对本对象有效果,对别的对象没有影响
p2=Person()
print(p2.name)

4.实例属性(对象属性)

  • 实例属性只能通过实例化对象调用,不能通过类名直接调用
#创建人类
class Person(object):
    # 初始化方法
    def __init__(self):
        #实例属性
        self.age = 18

#实例属性只能通过实例化对象调用,不能通过类名直接调用
p=Person()
print(p.age)

四、类方法、静态方法和实例方法

1.类方法

  • 是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法
  • 对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称,最好用cls)
  • 类方法能够通过实例对象和类名去访问
#创建人类
class Person(object):
    #类属性
    age=18
    #定义类方法
    @classmethod
    def get_age(cls):
        print(cls.age)

#类方法通过实例化对象调用
p=Person()
p.get_age()
#类方法通过类名直接调用
Person.get_age()

2.类方法对类属性进行修改

  • 类方法对类属性修改,通过类名和实例对象访问都发生了改变,不同对象访问也发生改变
#创建人类
class Person(object):
    #类属性
    age=18
    #定义类方法
    @classmethod
    def set_age(cls,age):
        cls.age=age
    @classmethod
    def get_age(cls):
        print(cls.age)

#类方法通过实例化对象调用
p=Person()
p.get_age()
#类方法通过类名直接调用
Person.get_age()
#通过类方法修改类属性,通过类名和实例对象访问都发生了改变
p.set_age(66)
p.get_age()
Person.get_age()
#不同对象也改变
p2=Person()
p2.get_age()

3.静态方法

  • 通过修饰器@staticmethod来进行修饰
  • 静态方法不需要多定义参数
  • 静态方法可以通过实例化对象和类名来访问
#创建人类
class Person(object):
    #类属性
    country="china"
    #定义静态方法
    @staticmethod
    def get_country():
        return Person.country

#静态方法通过实例化对象调用
p=Person()
print(p.get_country())
#静态方法通过类名直接调用
print(Person.get_country())

4.实例方法

  • 实例方法中需要self参数,因此实例方法只能通过实例化对象调用
  • 相较于普通方法多了self
  • self所表示的是实际调用该方法的对象
class Person(object):
    #定义实例方法,也就是普通的方法
    def self_method(self):
        print("我是实例方法")

#实例方法只能通过实例化对象调用
p=Person()
p.self_method()

五、单例模式

1.定义:永远用一个对象的实例,避免新建太多实例浪费资源

2.实质:使用__new__方法新建类对象时先判断是否已经建立过,如果建过就使用已有的对象

3.扩展:Python中的None

  • None是一个空值,空值是Python里的一个特殊值,用None表示。可以将None赋值给任何变量
  • None有自己的数据类型,它属于NoneType类型。None是NoneType数据类型的唯一值
  • None不等于空字符串、空列表、0,也不等同于False
  • None是一个特殊的空对象,可以用来占位
  • 对于定义的函数,如果没有return语句,在Python中会返回None;如果有不带值的return语句,那么也是返回None
  • 对于定义的函数,如果默认参数是一个可修改的容器如列表、集合或字典,可以使用None作为默认值

4.案例:

#单例模式
class Singleton():
    #类属性,用None充当占位符
    instance=None
    #初始化方法
    def __init__(self):
        print("我是初始化方法")
    #new方法
    def __new__(cls, *args, **kwargs):
        #判断实例对象是否存在
        if Singleton.instance:
            #存在则直接返回
            return Singleton.instance
        else:
            #不存在则新建一个实例对象
            Singleton.instance=object.__new__(cls)
            return Singleton.instance

#实例化对象,对象的地址值都相同
s1=Singleton()
print(id(s1))
s2=Singleton()
print(id(s2))