一、程序中定义类和对象
1、 定义类#
曾经定义函数,函数只检测语法,不执行代码,但是定义类的时候,类体代码会在类定义阶段就立刻执行,并且会产生一个类的名称空间,也就是说类的本身其实就是一个容器/名称空间,是用来存放名字的,这是类的用途之一。
# 注意类中定义变量使用驼峰体
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>
print(OldboyStudent.__dict__['choose_course'])
# <function __main__.OldboyStudent.choose_course(self)>
# <function OldboyStudent.choose_course at 0x00000000026FEEE0>
OldboyStudent.country = 'China'
print(OldboyStudent.__dict__['country'])
# 'China'
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) # OLDBOY2、定制对象独有特征
对象本质类似于类,也是一个名称空间,但是对象的名称空间存放对象独有的名字,而类中存放的是对象们共有的名字。因此我们可以直接为对象单独定制名字。
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 female3、对象属性查找顺序
首先从自身查找,没找到往类中找,类中没有则会报错。即对象的属性查找顺序为:自身--》类--》父类--》报错。
class OldboyStudent:
school = 'oldboy'
count = 0
aa = 10
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
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
print(stu1.name) # nick
# 由于上述修改的是类属性,类属性的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__功能的执行,将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'}三、对象的绑定方法
类名称空间中定义的数据属性和函数属性都是共享给所有对象用的
对象名称空间中定义的只有数据属性,而且是对象所独有的数据属性。
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。
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')