zoukankan      html  css  js  c++  java
  • Python(15):Python面向对象基础

    和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。

    Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。

    对象可以包含任意数量和类型的数据。

    一、程序中定义类和对象

    1、 定义类

    定义函数时,函数只检测语法,不执行代码,但是定义类的时候,类体代码会在类定义阶段就立刻执行,并且会产生一个类的名称空间,也就是说类的本身其实就是一个容器/名称空间(__dict__),是用来存放名字的,这是类的用途之一。

    语法格式如下:

    class ClassName:
        <statement-1>
        .
        .
        .
        <statement-N>

    类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。

    使用类名访问其属性:

    # 注意类中定义变量使用驼峰体
    class OldboyStudent():
        school = 'oldboy'
    
        def choose_course(self):
            print('is choosing course')
    
    
    print(OldboyStudent.__dict__)
    # {'__module__': '__main__', 'school': 'oldboy', 'choose_course': <function OldboyStudent.choose_course at 0x10d653ae8>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None}
    
    print(OldboyStudent.__dict__['school'])
    # oldboy
    
    
    print(OldboyStudent.__dict__['choose_course'])
    # <function OldboyStudent.choose_course at 0x10d653ae8>
    
    
    try:
        OldboyStudent.__dict__['choose_course']()
    except Exception as e:
        print('error:', e)
    # error: choose_course() missing 1 required positional argument: 'self'
    
    
    print(OldboyStudent.school)
    # oldboy
    
    
    print(OldboyStudent.choose_course(111))
    # is choosing course
    
    
    print(OldboyStudent.choose_course)
    # <function OldboyStudent.choose_course at 0x10d653ae8>
    
    
    OldboyStudent.country = 'China'
    print(OldboyStudent.__dict__['country'])
    # 'China'
    
    
    del OldboyStudent.school
    print(OldboyStudent.__dict__)
    # {'__module__': '__main__', 'choose_course': <function OldboyStudent.choose_course at 0x00000000026FEEE0>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None, 'country': 'CHINA'}

    2、 定义对象

    调用类即可产生对象,调用类的过程,又称为类的实例化,实例化的结果称为类的对象/实例。

    stu1 = OldboyStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
    print(stu1.school)  # oldboy
    
    stu2 = OldboyStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
    print(stu2.school)  # oldboy
    
    stu3 = OldboyStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
    stu3.choose_course()  # is choosing course

    二、定制对象独有特征

    1、引入

    对于上述的学生类,如果类的属性改了,则其他对象的属性也会随之改变

    class OldboyStudent():
        school = 'oldboy'
    
        def choose_course(self):
            print('is choosing course')
    
    
    stu1 = OldboyStudent()
    stu2 = OldboyStudent()
    
    OldboyStudent.school = 'OLDBOY'
    print(stu1.school)  # OLDBOY
    
    print(stu2.school)  # OLDBOY

    2、定制对象独有特征

    对象本质类似于类,也是一个名称空间,但是对象的名称空间存放对象独有的名字,而类中存放的是对象们共有的名字

    因此我们可以直接为对象单独定制名字。

    print(stu1.__dict__)  # {}
    print(stu2.__dict__)  # {}
    
    stu1.name = 'tank'
    stu1.age = 18
    stu1.gender = 'male'
    
    print(stu1.name, stu1.age, stu1.gender)
    # tank 18 male
    
    try:
        print(stu2.name, stu2.age, stu2.gender)
    except Exception as e:
        print(e)
    # 'OldboyStudent' object has no attribute 'name'
    
    stu2.name = 'sean'
    stu2.age = 19
    stu2.gender = 'female'
    
    print(stu2.name, stu2.age, stu2.gender)
    # sean 19 female

    3、对象属性查找顺序

    首先从自身查找,没找到往类中找,类中没有则会报错。即对象的属性查找顺序为:自身—>类—>父类—>报错。

    class OldboyStudent:
        school = 'oldboy'
        count = 0
        aa = 10 #类的的公共变量aa
    
    
        def __init__(self, x, y, z):  # 会在调用类时自动触发
            self.name = x  # stu1.name='耗哥'
            self.age = y  # stu1.age=18
            self.sex = z  # stu1.sex='male'
            OldboyStudent.count += 1
            # self.count += 1
            self.aa = 1 #对象的私有变量aa
    
        def choose_course(self):
            print('is choosing course')
    
    
    print(OldboyStudent.count)  # 0
    
    stu1 = OldboyStudent('nick', 18, 'male')
    print(stu1.count)  # 1
    
    stu2 = OldboyStudent('sean', 17, 'male')
    print(stu2.count)  # 2
    
    stu3 = OldboyStudent('tank', 19, 'female')
    print(stu3.count)  # 3
    
    print(OldboyStudent.count)  # 3
    
    
    # 由于上述修改的是类属性,类属性的count已经被修改为3,所以其他实例的count都为3
    print(stu1.count)  # 3
    print(stu2.count)  # 3
    print(stu3.count)  # 3
    
    # 由于aa是私有属性,因此stu们都会用自己私有的aa,不会用类的aa。count也不属于对象
    print(stu1.__dict__)  # {'name': 'nick', 'age': 18, 'sex': 'male', 'aa': 1}
    print(stu2.__dict__)  # {'name': 'sean', 'age': 17, 'sex': 'male', 'aa': 1}
    print(stu3.__dict__)  # {'name': 'tank', 'age': 19, 'sex': 'female', 'aa': 1}

    4、类定义阶段定制属性

    类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用。

    调用类时发生两件事:

    1. 创造一个空对象
    2. 自动触发类中__init__功能的执行,将stu1以及调用类括号内的参数一同传入。
    class OldboyStudent:
        school = 'oldboy'
    
        def __init__(self, name, age, gender):
            """调用类的时候自动触发"""
            self.name = name
            self.age = age
            self.gender = gender
            print('*' * 50)
    
        def choose_course(self):
            print('is choosing course')
    
    
    try:
        stu1 = OldboyStudent()
    except Exception as e:
        print(e)
    # __init__() missing 3 required positional arguments: 'name', 'age', and 'gender'
    
    stu1 = OldboyStudent('nick', 18, 'male')
    # **************************************************
    
    
    print(stu1.__dict__) 
    # {'name': 'nick', 'age': 18, 'gender': 'male'} #没有school
    

    三、对象的绑定方法

    • 类名称空间中定义的数据属性和函数属性都是共享给所有对象用的

    • 对象名称空间中定义的只有数据属性,而且是对象所独有的数据属性。

    1、类使用对象的绑定对象

    类中定义的函数是类的函数属性,类可以使用它,但使用的就是一个普通的函数而已,意味着需要完全遵循函数的参数规则,该传几个值就传几个

    class OldboyStudent:
        school = 'oldboy'
    
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.sex = gender
    
        def choose_course(self):
            print(f'{self.name} choosing course')
    
        def func(self):
            print('from func')
    
    
    print(OldboyStudent.choose_course)
    # <function OldboyStudent.choose_course at 0x00000000023AEF70>
    
    try:
        OldboyStudent.choose_course(123)
    except Exception as e:
        print(e)
    # 'int' object has no attribute 'name'

    2、对象使用对象的绑定方法

    • 类中定义的函数是共享给所有对象的,对象也可以使用,而且是绑定给对象用的,

    • 绑定的效果:绑定给谁,就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入

    类中定义的函数,类确实可以使用,但其实类定义的函数大多情况下都是绑定给对象用的,所以在类中定义的函数都应该自带一个参数self。

    self代表类的实例,而非类

    类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self,self 代表的是类的实例。

    self 不是 python 关键字,我们把他换成 aaabbb也是可以正常执行的:

    class OldboyStudent:
        school = 'oldboy'
    
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.sex = gender
    
        def choose_course(self):
            print(f'{self.name} choosing course')
    
        def func(self):
            print('from func')
    
    
    
    stu1 = OldboyStudent('nick', 18, 'male')
    stu2 = OldboyStudent('sean', 17, 'male')
    stu3 = OldboyStudent('tank', 19, 'female')
    
    stu1.choose_course() #相当于 stu1.choose_course(stul) 对象调对象绑定的方法,会自动传参
    # nick choosing course
    
    stu2.choose_course()
    # sean choosing course
    
    stu3.choose_course()
    # tank choosing course
    
    stu1.func()
    # from func
    stu2.func()
    # from func

    四、类与数据类型

    python3中统一了类与类型的概念,类就是类型

    class Foo:
        def __init__(self,name):
            self.name = name
    
    f = Foo('name')
    
    obj = Foo()
    print(type(obj))
    # <class '__main__.Foo'>
    
    
    lis = [1, 2, 3] # 相当于 lis = list([1,2,3])
    print(type(lis))
    # <class 'list'>

    lis.append(4)  # 对象调对象绑定的方法,会自动传参
    list.append(lis,4)  # 类调用对象绑定的方法,必须得传参

    对象其实就是一个高度整合的产物,整合数据与专门操作该数据的方法(绑定方法)

    import pymysql
    
    class Foo:
        def __init__(self, host, port, db, chartset):
            self.host = host
            self.port = port
            self.db = db
            self.charset = chartset
    
        def exc1(self, sql):
            conn = pymysql.connect(self.host, self.port, self.db, self.charset)
            conn.execute(sql)
            return xxx
    
        def exc2(self, proc_name):
            conn = pymysql.connect(self.host, self.port, self.db, self.charsett)
            conn.call_proc(proc_name)
            return xxx
    
    
    obj1 = Foo('1.1.1.1', 3306, 'db1', 'utf-8')
    obj1.exc1('select * from t1')
    obj1.exc1('select * from t2')
    
    obj2 = Foo('1.1.1.2', 3306, 'db1', 'utf-8')
    obj2.exc1('select * from t4')
  • 相关阅读:
    Java学习笔记二:发展史之Java的发展
    Java学习笔记一:发展史之Java诞生前
    JPA学习笔记四:理论篇之CRUD
    JPA学习笔记二:实践篇之SpringBoot集成JPA
    JPA学习笔记一:理论篇之JPA介绍
    JPA学习笔记三:实践篇之实现正向工程
    MySQL:大表优化
    如何理解原型链中的prototype和__proto__?
    Node版本的升级和降级
    常用的git提交代码命令
  • 原文地址:https://www.cnblogs.com/springsnow/p/11984938.html
Copyright © 2011-2022 走看看