之前一直拿python当c这类函数式语言来用,虽然够用了,但python作为面向对象的语言最核心的还是类


在Python中,类id定义使用class关键字来实现,语法如下:

class ClassName:
    '''类的帮助信息'''
    statement

下面的笔记代码需配合吉林大学出版社<Python从入门到项目实践>中的第12章-类和对象来品尝。

# _*_ coding : UTF-8 _*_
# 开发团队 : 泽塔云产品部
# 开发人员 : 肖昌鑫
# 开发工具 : Visual Studio Code

# ------------------------------ #
# 尝试使用类的方式来使用ssh,同时学习类
# 参考书籍:吉林大学出版社<Python从入门到项目实践>
# https://www.zhihu.com/question/266521768
# ------------------------------ #
class SshCon:   # 指定驼峰类名:SshCon,ssh连接的类名,作为基类
    # 创建类属性,在类的所有实例之间共享数值,在函数体外。应该在这里存放类的特征的
    error_codes = "zqa-e-0x001" # 定义一个类属性:错误代码,使用十六进制
    product_codes = "zqa-p-0x001" #定义一个类属性:产品代码,使用十六进制
    control_codes = "zqa-c-0x001"  #定义一个类属性:控制代码,使用十六进制
    status_codes = "zqa-s-0x001"   # 定义一个类属性:状态代码,使用十六进制

    node_name = "node01"    # 定义一个类属性,节点名称,用来测试继承

    # 访问限制
    ## 首尾双下划线表示定义特殊方法,一般是系统定义名字,如__init_()
    
    ## 以单下划线开头的表示protected(保护)类型的成员,只允许类本身和子类进行访问,但不能使用"from module import *"语句导入
    _server_ip = "1.1.1.1"
    ## 双下划线表示private(私有)类型的成员,只允许定义该方法的类本身进行访问,而且也不能通过类的实例进行访问,但是可以通过"类的实例名.类名__xxx”方式访问。
    __server__ip = "114.114.114.114"

    def __init__(self,server_ip,port,username,password):        # 构造方法,必须包含self参数,且必须是第一个参数,self参数是一个指向实例本身的引用,用于访问类中的属性和方法。
        # 这里也可以存放类的特征的
        self.server_ip = server_ip       # 定义实例属性(服务器IP)
        self.port = port                 # 定义实例端口(服务器端口)
        self.username = username         # 定义实例用户名(服务器的用户名)
        self.password = password         # 定义实例的密码(服务器的密码)
        print("通过ssh连接&管理服务器。")
        print("服务器的相关信息为:")
        print(self.server_ip) # 通过实例属性输出服务器IP
        print(self.server_ip) # 通过实例属性输出服务器端口
        print(self.username)  # 通过实例属性输出服务器用户名
        print(self.password)  # 通过实例属性输出服务器的密码
        
        print("压测的错误代码为:")     # 在这里也可以定义类的属性,比如:SshCon.error_codes=xxx 这样使用
        print(SshCon.error_codes)   # 输出类属性错误代码
        print(SshCon.product_codes) # 输出类属性产品代码
        print(SshCon.control_codes) # 输出类属性控制代码
        print(SshCon.status_codes)  # 输出类属性状态代码
        # ---------- #
        print("__init__() 访问保护属性_server_ip:",SshCon._server_ip) # 在实例方法中访问保护属性
        # ---------- #
        print("__init__() 访问私有属性__server__ip:",SshCon.__server__ip) # 在实例方法中访问私有属性
        # ---------- #
        self.bs = 1     # 块的大小
        self.count = 1024   # 块的数量
        # ---------- #
        self.__disk_size = "1t"   # 硬盘的大小,在这里设置为私有属性

    # 普通的方法,访问时需要带括号。
    def general_output(self,node_name):
        print("普通的方法,没有带装饰器,访问时需要带小括号")
        print("SshCon的普通方法node_name形参为:",node_name) # 输出的是形式参数node_name
        print("SshCon的普通方法node_name类属性为:",SshCon.node_name) # 输出类属性,节点名称
        
    # 在class类定义函数可以通过装饰器转化为属性时使用,装饰器本质上就是一个函数,这个函数接收其他函数作为参数,并将其以一个新的修改后的函数进行替换。
    # 装饰器的简介:http://mingxinglai.com/cn/2015/08/python-decorator/,
    @property   # 将方法转化为属性,为用于计算的属性,将方法转化为属性后,可以直接通过方法名来访问方法,而不需要再添加一堆小括号"()",这样可以让代码更简洁。
    def dd_disk_size(self):    # 计算dd硬盘总共占用块的大小的方法
        return self.bs*self.count   # 返回块的大小

    @property # 将方法转化为属性,这里是为了只读
    def disk_size(self):    # 这里定义disk_size方法,用来返回disk_size
        return self.__disk_size # 返回私有属性的值,实现访问只读属性

# ---------- #
# 使用继承的方式,表示这个类拥有它继承的类的所有公有成员或受保护成员,没有私有类型成员。
class SshScp(SshCon):   # 定义派生类,SshScp,被继承的基类是SshCon
    node_name = "node02"    # 修改一个类属性,节点名称
    def __init__(self,server_ip,port,username,password):
        print("\nSshScp派生类")
        super().__init__(server_ip,port,username,password)  # 派生类不能直接调用基类的__init__()方法,当在派生类中使用基类的函数时,需要使用super()进行初始化
                                                            # 在派生类中初始化基类的时候,基类带有的server_ip,port,username,password,派生类也需要提供
                                                            # 在派生类中初始化基类的__init__()方法时候,会再次执行一次基类__init__()中的print
    def general_output(self,node_name):
        print("通过继承的方法使用general_output")
        print("SshScp的普通方法node_name形参为:",node_name) # 输出的是形式参数node_name
        print("SshScp内输出SshCon的普通方法node_name类属性为:",SshCon.node_name) # 输出类属性,节点名称
        print("SshScp内输出SshScp的普通方法node_name类属性为:",SshScp.node_name) # 输出类属性,节点名称
    

if __name__ == '__main__':
    node_name = "main_node"
    server_ip = "192.168.178.30"
    port= 22
    username = "root"
    password = "mima"

    install_disk_stress = SshCon(server_ip,port,username,password)  # 实例化一个ssh类的对象
    # ---------- #
    # 通过调用实例名的方式访问类,可以防止不断重新初始化类。
    ssh_1 = SshCon(server_ip,port,username,password)    # 创建SshCon类的实例名1,创建实例名的时候class内的__init__的print依然会运行
    ssh_2 = SshCon(server_ip,port,username,password)    # 创建SshCon类的实例名2,创建实例名的时候class内的__init__的print依然会运行
    ssh_1.server_ip = "1.0.0.1"                         # 修改实例属性
    print("ssh_1的IP实例属性:",ssh_1.server_ip)
    print("ssh_2的IP实例属性:",ssh_2.server_ip)
    # ---------- #
    print("直接访问保护属性_server_ip:",ssh_2._server_ip)       # 保护属性可以通过实例名访问
    # ---------- #
    print("加入类名访问私有属性__server__ip:",ssh_2._SshCon__server__ip)    # 私有属性,可以通过"类的实例名.类名__xxx”方式访问。
    # print("直接访问私有属性__server__ip:",ssh_2.__server__ip)    # 私有属性不能通过"类的实例名.__xxx”方式访问。
    # ---------- #
    ssh_2.general_output(node_name)  # 普通的方法,访问时需要带括号,这样可以把参数也传递进去。
    # ---------- #
    print("使用装饰器的计算属性,不需要小括号,硬盘dd块的大小为:",ssh_2.dd_disk_size)
    # ---------- #
    print("使用装饰器的只读属性,硬盘的大小为:",ssh_2.disk_size)
    # ---------- #
    ssh_3 = SshScp(server_ip,port,username,password)    # 创建SshScp派生类的实例名3,创建实例名的时候class内的__init__的print依然会运行
    ssh_3.general_output(node_name)  # 普通的方法,访问时需要带括号。
    # ---------- #
    print("在派生类中,使用基类的方法---硬盘dd块的大小为:",ssh_3.dd_disk_size)
最后修改:2022 年 11 月 02 日
如果觉得我的文章对你有用,请随意赞赏