【Python知识点梳理】6.面向对象基础(下)

6.面向对象基础(下)



1、私有化属性

  私有化属性的概念:
 1.封装的体现: 私有化属性、私有化方法
 2.在面向对象过程中,修改类属性都是直接通过类名修改的。如果有些重要属性不想随便修改,或者防止意外修改,为了更好的保存属性安全,将属性定义为私有属性,添加一个可调用的方法去访问。
 3.使用两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。
  使用私有属性的场景:
 1.把特定的一个属性隐藏起来,不想让类的外部进行直接调用(私有化属性不能在类外面访问)
 2.保护这个属性,不想让属性的值随意的改变(私有化属性可以在类里面访问,修改。)
 3.保护这个属性,不想让派生类(子类)去继承(子类不能继承私有化属性。)

# 1.定义一个具有两个公共实例属性的类
class Person(object):
    def __init__(self):  # 定义两个实例属性
        self.name = "Tracy"  # 公共的属性
        self.age = 18


Ty = Person()
print(Ty.age)
print(Ty.name)
# 2.对实例属性进行私有化
class Person(object):
    def __init__(self):
        # 加两个下划线,属性私有化。
        self.__name = "Tracy"  # 不能再外部直接访问,在类的内部是可以访问
        self.age = 18


# 私有化的属性不能再外部访问(报错)
Ty = Person()
print(Ty.age)  
print(Ty.name)  # 通过类对象在外部不能访问私有属性
# 3.在内部访问私有化的实例属性
class Person(object):
    def __init__(self):
        self.__name = "Tracy"
        self.age = 18

    # 私有化的实例属性可以在类里面访问,修改。
    def __str__(self):
        return "{}的年龄是{}".format(self.__name, self.age)


Ty = Person()
print(Ty)  # 私有化的属性在内部可以使用
# 4.私有化的实例属性的继承
class Person(object):
    def __init__(self):
        self.__name = "Tracy"
        self.age = 18

    def __str__(self):
        return "{}的年龄是{}".format(self.__name, self.age)


class Student(Person):
    pass


stu = Student()
print(stu.age)
print(stu.__name)  # 子类的实例不能继承私有化属性
# 5.私有化的实例属性的继承
class Person(object):
    def __init__(self):
        self.__name = "Tracy"
        self.age = 18

    def __str__(self):
        return "{}的年龄是{}".format(self.__name, self.age)


class Student(Person):
    def PrintInfo(self):
        print(self.age)
        print(self.__name)  # 访问父类中的私有属性
    pass


stu = Student()
stu.PrintInfo()

  小结:
 1.私有化的实例属性,不能在外部直接的访问,可以在类的内部随意的使用。
 2.子类不能继承父类的私有化属性,只能继承父类公共的属性和方法。
 3.在属性名的前面直接加__(双下划线) ,进行私有化操作。

# 6.定义一个具有类属性的类
class Person:
    hobby = '跳舞'

    def __init__(self):
        self.__name = 'Tracy'
        self.age = 30
        pass


class Student(Person):
    def printInfo(self):
        print(self.age)
    pass


stu = Student()

stu.printInfo()
print(stu.hobby)  # 实例对象访问类属性
print(Person.hobby)  # 类对象访问类属性
# 7.对类属性进行私有化
class Person:
    __hobby = '唱歌'  # 私有的类属性

    def __init__(self):
        self.__name = 'Tracy'  # 定义一个私有实例属性
        self.age = 30
        pass

    def __str__(self):

        # 类的私有化的属性在内部可以使用 类名.__xxx
        return '{}的年龄是{},爱好是{}'.format(self.__name, self.age, Person.__hobby)

    def changeValue(self, hobby):
        Person.__hobby = hobby  # 修改类的私有实例属性


class Student(Person):
    def printInfo(self):
        # print(self.__name)  # 访问父类中的私有属性(不可以)
        print(self.age)
    pass


stu = Student()
# print(stu.__name)
stu.printInfo()
stu.changeValue("跳舞")  # 修改类的私有属性的值
print(stu)
# print(stu.__hobby)     #实例对象访问类属性
# print(Person.__hobby)  #类对象访问类属性
# 8 修改类的私有属性
class Person(object):
    __age = 18 # 定义一个私有化属性,属性名前加两个下划线
    
    def get_age(self):
        return Person.__age
    
    def set_age(self,age):
        Person.__age = age
        
AGE = Person()
print(AGE.get_age())

AGE.set_age(28)
print(AGE.get_age())

2、私有化方法

  概念:私有化方法和私有化属性概念一样,有些重要的方法,不允许外部使用,防止子类意外重写,因此把一些方法设置为私有化方法,在方法名前加两个下划线。
  特性:私有化方法一般是内部调用,子类不能继承,外部不能调用。

class Animal(object):
    # 在方法名前加两个下划线,变成私有化方法
    def __eat(self):
        print("吃东西!")

    def run(self):
        print("跑得飞快!")
        self.__eat()  # 在此调用私有化的方法
        pass
    pass


class Bird(Animal):
    pass


b1 = Bird()
b1.run()

b1.__eat() # 调用私有化方法(报错)

  单下划线、双下划线、头尾双下划线说明:
 1._xxx 前面加一个下划线,以单下划线开头的表示的是 protected(保护)类型的变量,即保护类型只能允许其本身与子类进行访问,不能使用from xxx import * 的方式导入。
 2.__xxx__ 前后两个下滑线,魔法方法,一般是python自有,开发者不要创建这类型的方法。
 3.xxx_ 后面单下滑线,避免属性名与python关键字冲突。

# 私有化方法案例
class Details:
    def __init__(self):
        self.__ids = "<No Id>"  # 私有实例属性写为固定值
        self.__name = "<No Name>"
        self.__gender = "<No Gender>"

    def setData(self, ids, name, gender):
        self.__ids = ids       # 修改私有实例属性的值
        self.__name = name
        self.__gender = gender

    def showData(self):
        print("Id\t\t:", self.__ids)
        print("Name\t\t:", self.__name)
        print("Gender\t\t:", self.__gender)


class Employee(Details):  # Inheritance
    def __init__(self):
        self.__company = "<No Company>"
        self.__dept = "<No Dept>"

    def setEmployee(self, ids, name, gender, comp, dept):
        self.setData(ids, name, gender)  # 调用父类的方法
        self.__company = comp
        self.__dept = dept

    def showEmployee(self):
        self.showData()
        print("Company\t\t:", self.__company)
        print("Department\t:", self.__dept)


e = Employee()
e.setEmployee(101, "Prem Sharma", "Male", "New Delhi", 110065)
e.showEmployee()

3、Property属性

  属性函数(property)帮助调用者实现通过属性的形式去访问已经私有化的方法或属性。注意:必须是以get,set开头的方法名,才能被调用。

# 访问私有变量,一般写两个方法:一个访问,一个修改,由方法去控制访问。
class Person(object):
    def __init__(self):
        self.__age = 15

    def get_age(self):  # 访问
        return self.__age

    def set_age(self, age):  # 修改
        if age < 0:
            print("年龄不能小于零!")
        else:
            self.__age = age


nl = Person()
print(nl.get_age())
nl.set_age(29)
print(nl.get_age())
# 实现方式-1
# 类属性,即在类中定义值为property对象的类属性
# 示例:给age属性设置值时,会自动调用set_age方法;获取age属性值时,会自动调用get_age方法。
class Person(object):
    def __init__(self):
        self.__age = 15  # 定义一个私有化属性,属性名字前加连个 __ 下滑线

    def get_age(self):  # 访问私有实例属性
        return self.__age

    def set_age(self, age):  # 修改私有实例属性
        if age < 0:
            print("年龄不能小于零!")
        else:
            self.__age = age

    # 定义一个类属性,实现通过直接访问属性的形式去访问私有属性
    age = property(get_age, set_age)    # 定义一个属性,当对这个age设置值时调用set_age,
                                        # 当获取值时调用get_age
                                        # 注意:必须是以get,set开头的方法名,才能被调用


ni = Person()
print(ni.age) # 访问
ni.age = 29   # 修改
print(ni.age)
# 实现方式-2
# 装饰器,即在方法上使用装饰器
class Person(object):
    def __init__(self):
        self.__age = 15  # 定义一个私有化属性,属性名字前加连个 __ 下滑线

    @property  # 使用装饰器对age进行装饰,提供一个getter方法
    def age(self):  # 访问私有实例属性
        return self.__age

    @age.setter  # 使用装饰器进行装饰,提供一个 函数名.setter 方法
    def age(self, pram):  # 修改私有实例属性
        if pram < 0:
            print("年龄不能小于零!")
        else:
            self.__age = pram


xiaoming = Person()
print(xiaoming.age)
xiaoming.age = 29
print(xiaoming.age)

4、__new__方法

  概述:__new__()方法的作用是,创建并返回一个实例对象,如果__new__()只调用了一次,就会得到一个新的对象。继承自object的新式类才有__new__()魔法方法。
  注意事项:
 1.__new__()是在一个对象实例化的时候所调用的第一个方法。
 2.__new__()至少必须要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供,其他的参数是用来直接传递给__new__()方法。
 3.__new__()决定是否要使用该__init__()方法,因为__new__()可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果__new__()没有返回实例对象,则__init__()不会被调用。
 4.在__new__()方法中,不能调用自己的__new__()方法,即:return cls.__new__(cls),否则会报错(RecursionError: maximum recursion depth exceeded:超过最大递归深度)。

# __new__()方法在__init__()方法之前执行
class A(object):
    def __init__(self):
        print("__init__执行了!")

    def __new__(cls, *arg, **kwarg):  # 静态方法
        print("__new__执行了!")
        return object.__new__(cls)


a = A()
class Animal:
    def __init__(self):
        self.color = '红色'
        pass
    
    # 在python当中, 如果不重写 __new__()默认结构如下
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)
        # return object.__new__(cls, *args, **kwargs)
    pass


tigger = Animal()  # 实例化的过程会自动调用__new__去创建实例
# 在新式类中__new__()才是真正的实例化的方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__()进行丰满操作
# 比喻建房子__new__()方法负责开发地皮打地基,并将原料存放在工地,而__init__()负责从工地取材料建造出地皮开发图纸规定的大楼,
# 负责细节设计、建造 最终完成
class A(object):
    def __init__(self, a, b, c, k):
        print(a, b, c, k)
        print("__init__执行了")
    
    def __new__(cls, *args, **kwargs):
        return object.__new__(cls)  # 调用父类的new方法

a = A(1, 2365, 1122, k=3)

5、单例模式

  单例模式是常用设计模式的一种,单例就比如打开电脑的回收站,在系统中只能打开一个回收站,也就是说这个整个系统中只有一个实例,重复打开也是使用这个实例。
  简单的说就是不管创建多少次对象,类返回的对象都是最初创建的,不会再新建其他对象。
  确保某一个类只有一个实例存在。

# 实现案例-1
# 利用类属性保存初次创建的实例对象,第二次实例化的时候判断类属性是否有保存实例对象
# 如果有就返回类属性保存的,如果没有就调用父类__new__方法创建新的实例对象。
class SingleCase(object):
    __instance = None  # 保存实例对象

    def __init__(self, name, age):
        print(name, age)

    def __new__(cls, *args, **kwargs):
        # 如果类属性 __instance 的值为None,那么新建一个对象
        # 如果类属性值不为None 返回 __instance 保存的对象
        if not cls.__instance:
            # cls.__instance = cls.__new__(cls) 不能用自身的nwe方法,造成深度递归
            cls.__instance = super(SingleCase, cls).__new__(cls)  # 调用父类__new__方法生成一个实例对象
            return cls.__instance
        else:
            return cls.__instance
        
class A(SingleCase):
    pass


obj1 = A('Tom', 18)
obj2 = A('Jarry', 28)
print(id(obj1))  # id相等,说明实例化两次对象,实际上都是同一个对象
print(id(obj2))
# 实现案例-2
# 只执行一次init方法,通过类变量进行标记控制
class SingleCase(object):
    __instance = None  # 保存实例对象
    __isinit = True    # 首次执行init方法标记

    def __init__(self, name, age):
        if SingleCase.__isinit:
            self.name = name
            self.age = age
            SingleCase.__isinit = False

    def __new__(cls, *args, **kwargs):  # 如果类属性 __instance 的值为None,那么新建一个对象
        # 如果类属性值不为None 返回 __instance 保存的对象
        if not cls.__instance:
            cls.__instance = super(SingleCase, cls).__new__(
                cls)  # 调用父类__new__方法生成一个实例对象
            return cls.__instance
        else:
            return cls.__instance


obj1 = SingleCase('Tom', 18)
obj2 = SingleCase('Jarry', 118)
print(id(obj1))
print(id(obj2))
print(obj1.age)
print(obj2.age)  # 年龄都输出18。说明init值初始化了一次

6、错误与异常处理

  有时候代码写错了,执行程序的时候,执行到错误代码的时候,程序直接终止报错,这是因为Python检测到一个错误时,解释器就无法继续执行了,出现了错误的提示,这就是"异常"。
  Exception可以捕获任何类型的异常!!!

try:
    可能出现错误的代码块

except:
    出错之后执行的代码块

else:
    没有出错的代码块

finally:
    不管有没有出错都执行的代码块

说明:except在捕获错误异常的时候只要根据具体的错误类型来捕获的
import platform

# 查看Python当前使用版本
print(platform.python_version())

# 查看Python内置函数(错误与异常)
print(dir(__builtins__))
    异常	        导致的错误
AssertionError	 当assert语句失败时引发。
AttributeError	 当属性分配或引用失败时引发。
EOFError	 当input()函数达到文件结束条件时引发。
FloatingPointError	 当浮点运算失败时引发。
GeneratorExit	 调用生成器的close()方法时引发。
ImportError	 找不到导入的模块时引发。
IndexError	 当序列的索引超出范围时引发。
KeyError	 在字典中找不到键时引发。
KeyboardInterrupt	 当用户按下中断键(Ctrl+c或delete)时引发。
MemoryError	  当操作耗尽内存时引发。
NameError	  在局部或全局范围内找不到变量时引发。
NotImplementedError	 由抽象方法提出。
OSError	 当系统操作导致系统相关错误时引发。
OverflowError	 当算术运算的结果太大而无法表示时引发。
ReferenceError	 使用弱引用代理访问垃圾收集的引用时引发。
RuntimeError	 当错误不属于任何其他类别时引发。
StopIteration	 函数引发,以指示迭代器不再返回任何项。
SyntaxError	 遇到语法错误时由解析器引发。
IndentationError	 当缩进不正确时引发。
TabError	 当缩进由不一致的制表符和空格组成时引发。
SystemError	 当解释器检测到内部错误时引发。
SystemExit	 由sys.exit()函数引发。
TypeError	 将函数或操作应用于类型不正确的对象时引发。
UnboundLocalError	 当在函数或方法中引用局部变量,但没有将值绑定到该变量时引发。
UnicodeError	 当发生与unicode相关的编码或解码错误时引发。
UnicodeEncodeError	 当编码过程中发生与unicode相关的错误时引发。
UnicodeDecodeError	 当解码过程中出现与unicode相关的错误时引发。
UnicodeTranslateError	 翻译过程中发生与unicode相关的错误时引发。
ValueError	 当函数得到类型正确但值不正确的参数时引发。
ZeroDivisionError	 当除法或模运算的第二个操作数为零时引发。
 1 try ... except语句
# 将可能出错的代码放到try里面,except可以指定类型捕获异常。
# except里面的代码是捕获到异常时执行, 将错误捕获,这样程序就不会因为一段代码包异常而导致整个程序崩溃。

# 示例1:捕获ZeroDivisionError异常
try:
    1/0  # 将可能会报错的代码放到try里面

except ZeroDivisionError as e:  # 捕获异常,ZeroDivisionError 异常类型
    print(e)
# 示例2:捕获所有类型的异常
try:
    print(s)

except Exception as e:  # Exception可以捕获任何类型的异常!!!
    print(e)  # 再次尽量要处理捕获到的异常
# 示例3:同一个try可以进行不同异常的捕获(根据具体的类型进行捕获)
try:
    # li = [1, 5, 6, 8]
    # print(li[10])
    a = 1/0
except NameError as e:
    print(e)

except IndexError as e:
    print(e)

except ZeroDivisionError as e:  # Exception可以捕获任何类型的异常!!!
    print(e)
# 2 try ... except ... else语句
# 没有捕获到异常时才执行else语句

# 示例:
try:
    print("--------test----------")
except Exception as e:  # Exception 可以捕获任何类型的异常
    print(e)
else:
    print("哈哈 --- 没有捕获到异常")  # 没有捕获到异常,将执行else里面代码,否则不执行

try:
    print("--------test----------")
    1/0
except Exception as e:  # Exception 可以捕获任何类型的异常
    print(e)
else:
    print("haha --- 没有捕获到异常")  # 捕获到异常不执行else的代码
# 3 try ... except ... finally语句
try:
    print("--------test----------")
except Exception as e:  # Exception 可以捕获任何类型的异常
    print(e)
else:
    print("哈哈 --- 没有捕获到异常")  # 没有捕获到异常,将执行else里面代码,否则不执行
finally:
    print("不管有没有捕获到异常,finally都是执行的")


try:
    print("--------test----------")  # try里面有异常
    1/0
except Exception as e:  # Exception 可以捕获任何类型的异常
    print(e)
else:
    print("哈哈 --- 没有捕获到异常")  # 捕获到异常,执行else 的代码
finally:
    print("不管有没有捕获到异常,finally都是执行的")
# 4 函数的异常捕获
def A(s):
    return 10/int(s)

def B(s):
    return A(s)*2

def main(): # 统一捕获
    try:
        B("0")
    except Exception as e:
        print(e)

main()  # 不需要在每个可能出错的地方去捕获,只要在适合的层次去捕获错误就可以。减少try--except的结构。
# 5 try嵌套
import time

try:
    f = open('test.txt', 'r')  # 打开一个文件

    try:
        while True:
            content = f.readline()
            if len(content) == 0:
                break
            time.sleep(2)
            print(content)

    except Exception as e:
        print(e)  # 打印捕获的异常
        # 如果在读取文件的过程中,产生了异常,那么就会捕获到
        # 比如 按下了 ctrl+c

    finally:
        f.close()
        print('关闭文件')

except Exception as e:
    print(e, '文件不存在')

  异常的抛出机制:
 1.如果在运行时发生异常 解释器会查找相应的异常捕获类型。
 2.如果在当前函数里面没有找到的话 它会将异常传递给上层的调用函数,看能否处理。
 3.如果在最外层没有找到的话,解释器就会退出程序。

# 6 异常传递
# 如果多个函数嵌套调用,内层函数异常,异常会往外部传递,直到异常被抛出,或被处理。
def a():
    print('执行a函数')
    1/0  # 制造一个异常
    print('a函数执行完成')

def b():
    print('执行b函数')
    a()  # 调用a函数
    print('b函数执行完成')

def c():
    print('执行c函数')

    try:
        b()  # 调用b函数
    except Exception as e:
        print(e)
        print('c函数执行完成')

c()
# 7 自定义异常,都要直接或间接继承Error或Exception类。
# 由开发者主动抛出自定义异常,在python中使用raise关键字,
class ToolongMyException(Exception):
    def __init__(self, leng):
        self.len = leng
        pass

    def __str__(self):
        return '您输入姓名数据长度是'+str(self.len)+',超过长度了..'
    pass


def name_Test():
    name = input('请输入姓名.....')
    try:
        if len(name) > 5:
            raise ToolongMyException(len(name))  # 抛出异常
        else:
            print(name)
            pass
        pass

    except ToolongMyException as result:  # 捕获异常
        print(result)
        pass

    finally:
        print('执行完毕了....')


name_Test()
# 8 自定义一个异常类
class LeNumExcept(Exception):  # 自定义异常类需要继承Exception
    def __str__(self):
        return '[error:]你输入的数字小于0,请出入大于0的数字'

    try:
        num = int(input('请输入一个数字:'))
        if num < 0:
            # raise 关键字抛出异常
            raise LeNumExcept()

    except LeNumExcept as e:
        print(e)  # 捕获异常

    else:
        print('没有异常')

7、Python动态添加属性和方法

  动态语言:运行时可以改变其结构的语言,例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。如php,JavaScript,Python都是动态语言,C,C#,java是静态语言。所以Python可以在程序运行过程中添加属性和方法。

# 动态添加实例属性
class Animal(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


cat = Animal("Cat", 2)
cat.color = "Yellow"  # 动态添加colour属性(实例属性)

print(cat.color)
print(cat.__dict__)
# 给对象动态添加属性的特点
class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return "{}同学{}岁了".format(self.name, self.age)


Tom = Student("Tom", 24)
Tom.weight = 75  # 动态添加weight属性(实例属性)
print(Tom)
print(Tom.weight)

print("- "*5, "另外一个实例对象", " -"*5)

Jarry = Student("Jarry", 21)
print(Jarry)
print(Jarry.weight) # 没有weight属性(实例属性)
# 运行中给类添加属性
class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return "{}同学{}岁了".format(self.name, self.age)


Student.school = "北京邮电大学"
Tom = Student("Tom", 24)
print(Tom.school) # 通过实例对象访问类属性
class Animal(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


cat = Animal('小白', 5)


cat.colour = '白色' # 动态添加colour实例属性
print(cat.colour)
Animal.foot = 4     # 动态添加foot类属性
print(cat.foot)

  动态添加实例方法需要使用types库。

# 动态添加实例方法
import types  # 导入添加方法的库


# 定义一个要添加的方法
def dymicMethod(self):
    print("{}同学的体重是{}kg,在{}读书!".format(self.name, self.weight, Student.school))


class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return "{}同学{}岁了".format(self.name, self.age)


    
Mack = Student("Mack", 24)

Student.school = "北京邮电大学"  # 动态添加school实例属性
Mack.weight = 75                 # 动态添加weight类属性

Mack.printinfo = types.MethodType(dymicMethod, Mack)  # 动态添加实例方法:实例对象.方法名 = types.MethodType(要添加方法名字,实例对象)

Mack.printinfo()  # 调用新添加的实例方法
print(Mack.__dict__)
# 给类绑定类方法和静态方法
# 使用方式:类名.方法名 = xxxx
class Animal(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

@classmethod  # 在外部定义的类方法
def eat(cls):
    print('吃东西')

@staticmethod  # 在外部定义的静态方法
def drink():
    print('喝水')

    
Animal.eating = eat   # 添加类方法:类名.方法名 = 外部定义的类方法名
Animal.eating()

Animal.drinking = drink  # 添加静态方法:类名.方法名 = 外部定义的类方法名
Animal.drinking()

cat = Animal('小白', 5)
cat.eating()
cat.drinking()
print(cat.__dict__)

8、__slots__属性

  Python是动态语言,在运行的时候可以动态添加属性。如果要限制在运行的时候给类添加属性,Python允许在定义class的时候,定义一个特殊的__slots__()变量,来限制该class实例能添加的属性。
  只有在__slots__()变量中的属性才能被添加,没有在__slots__()变量中的属性会添加失败。可以防止其他人在调用类的时候胡乱添加属性或方法。__slots__()属性子类不会继承,只有在当前类中有效。

class A(object):

    __slots__ = ('name', 'age') # 进行限制(魔术方法)

    def __str__(self):
        return "{}...{}".format(self.name, self.age)
    pass


a = A()
a.name = "旺财"
a.age = 5
a.weight = 75 # 没有在范围内,不能添加,所以报错
print(a)
print(a.__dict__) # 所有可以用的属性都在这里存储(字典类型)-->占用内存空间较大

# 所有可以用的属性都在这里存储  不足的地方就是占用的内存空间大
# 可以看到 在定义了 slots变量之后 A类的实例已经不能随意创建不在 __slots__定义的属性了
# 同时还可以看到实例当中也不在有__dict__
# 作用
# 限制要添加的实例属性
# 节约内存空间
class Student(object):
    __slots__ = ('name', 'age', 'score')

    def __str__(self):
        return '{}....{}'.format(self.name, self.age)
    pass


sut = Student()
sut.name = 'Zoop'
sut.age = 20
sut.score = 96  # 没有在范围内 所以报错
# print(sut.__dict__) #所有可以用的属性都在这里存储  不足的地方就是占用的内存空间大
# 可以看到,在定义了__slots__()变量之后,student类的实例已经不能创建不在__slots__()中定义的属性了
# 同时还可以看到实例当中也不在有__dict__
print(sut)


# 在继承关系当中的使用__slots__()
# 子类未声明__slots__()时,那么是不会继承父类的__slots__(),此时子类是可以随意添加属性
# 子类声明了__slots__()时,可以继承父类的__slots__(),子类__slots__()的范围是子类+父类的__slots__()范围

class subStudent(Student):
    __slots__ = ('gender', 'pro')
    pass


ln = subStudent()
ln.gender = '男'
ln.pro = '计算机信息管理'  # 子类的限制范围
ln.name = 'Tom'  # 继承父类的限制
print(ln.name, ln.gender, ln.pro)

练习

# 1、编写一段代码以完成下面的要求
# 定义一个Person类,类中要有初始化方法,方法中要有人的姓名,年龄两个私有属性.
# 提供获取用户信息的函数.
# 提供获取私有属性的方法.
# 提供可以设置私有属性的方法.
# 设置年龄的范围在(0-120)的方法,如果不在这个范围,不能设置成功.
class Person(object):
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def __str__(self):
        return "{}的年龄是:{}".format(self.__name, self.__age)

    def getAgeInfo(self):
        return self.__age

    def setAge(self, age):
        if age > 0 and age < 120:
            self.__age = age
        else:
            print('您输入的数据不合法')

    def getNameInfo(self):
        return self.__name

    def setName(self, name):
        self.__name = name


xz = Person("小张", 18)
print(xz)
print(xz.getAgeInfo())
print(xz.getNameInfo())
print("- "*3, "修改", " -"*3)
xz.setName("张伟")
xz.setAge(23)
print(xz)
print(xz.getAgeInfo())
print(xz.getNameInfo())
# 2、创建一个类,并定义两个私有化属性,提供一个获取属性的方法,和设置属性的方法。
# 利用property 属性给调用者提供属性方式的调用获取和设置私有属性方法的方式。
class Student(object):
    def __init__(self):
        self.__name = "张三"
        self.__score = 92

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, name):
        self.__name = name

    @property
    def score(self):
        return self.__score

    @score.setter
    def score(self, score):
        self.__score = score

    def __str__(self):
        return '{}的得分是:{}!!!'.format(self.__name, self.__score)

    def __call__(self, *args, **kwargs):
        print('{}的得分是:{}...'.format(self.__name, self.__score))


xw = Student()
xw()  # 将实例对象以函数的形式去调用
print(xw)
xw.name = '李四'
xw.score = 98
xw()
print(xw)
class Student(object):
    def __init__(self):
        self.__name = "老李"
        self.__score = 88

    def get_name(self):
        return self.__name

    def set_name(self, name):
        self.__name = name

    def get_score(self):
        return self.__score

    def set_score(self, score):
        self.__score = score

    name = property(get_name, set_name)
    score = property(get_score, set_score)

    def __str__(self):
        return '{}的得分是:{}!!!'.format(self.__name, self.__score)

    def __call__(self, *args, **kwargs):
        print('{}的得分是:{}...'.format(self.__name, self.__score))


xw = Student()
xw()  # 将实例对象以函数的形式去调用
print(xw)
xw.name = '王五'
xw.score = 90
xw()
print(xw)
# 3、创建一个Animal类,实例化一个cat对象,请给cat对象动态绑定一个run方法.
# 给类绑定一个类属性colour,给类绑定一个类方法打印字符串'ok'。
import types


class Animal:
    pass


def run(self):  # 实例方法
    print('小猫飞快的跑...')
    pass


@classmethod     # 类方法
def info(cls):
    print('ok')


cat = Animal()
cat.run = types.MethodType(run, cat)  # 动态添加实例方法
cat.run()

Animal.colour = '黑色'  # 动态添加类属性
Animal.info = info      # 动态添加类方法
print(cat.colour)
Animal.info()
print(cat.__dict__)

总结

1、Python中__new__()方法作用是什么?
 用来创建实例对象的,只有继承了object的,才能有这个方法

2、什么是单例模式?单例模式适用于什么场景?
  要求一个类有且只有一个实例,并且提供了一个全局的访问点
 场景:日志插入logger的操作,网站计数器,权限验证模块,window资源管理器、系统回收站,数据库连接池

3、私有化方法与私有化属性在子类中能否继承?
 不能

4、在Python中什么是异常?
  异常就是程序在执行的过程中发生的错误

5、Python中是如何处理异常的。
 分别根据异常的类型去处理

6、Python中异常处理语句的一般格式,可以使用伪代码的形式描述。

 try:
        可能出现错误的代码块
    except:
        出错之后执行的代码块
    else:
        没有出错的代码块
    finally:
        不管有没有错都执行的代码块

7、__slots__属性的作用
 限制属性的随意输入,节省内存空间(关闭__dict__)

8、私有化属性的作用?
 保护数据,封装性的体现

9、在类外面是否能修改私有属性。
 不可以直接修改的通过方法去实现,可以借助属性函数property去实现

10、如果一个类中,只有指定的属性或者方法能被外部修改。那么该如何限制外部修改。
 对属性进行私有化的设定

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器视觉小学徒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值