class Student: # 类名,同时创建同名的类对象和变量,类对象只能有一个
school='yyds' #类属性
def show(self,id,name,age,school): # 第一个参数必须是self,指的是当前类的实例
self.id=id# name,id,age是实例属性
self.name=name
self.age=age
self.school=school
print(self.id,self.name,self.age)# 创建一个实例
创建类的时候命名有以下几个规则:
1:用class关键字来定义类,命名格式如上
2:类名的首字母应大写,如上的Student(不是强制的,但是是一般的命名规则,这样命名不会出错)
3:方法命名的时候如果有多个单词第一个单词首字母不用大写,其余的单词首字母大写
4:我们再给属性或方法命名的时候通过下划线来表示变量的类别:_foo(左边有一个下划线),表示只允许本身及其子类应用;__foo(左边有两个下划线,表示是私有类型),只允许这个类本身访问; __ foo __(左右各有两个下划线,表示python的内置函数)
一个类主要由以下六个要素组成:
类对象、实例对象、类属性、实例属性、类方法、实例方法。
以上已经说明,用(class+类名)创建,创建类名的同时还自动创建类对象和量,名称就是类名称,这里要注意的是类对象只能有一个。
实例对象通过调用类对象来创建,如下所示:
s1=Student() #创建一个实例对象,继承其所有的实例方法
通过以上的代码,我们创建了一个实例对象,这里实例对象会继承所有的实例方法,实例属性等
如果类中有相同的类属性和实例属性,那么通过实例对象只能访问实例属性,如下所示的代码:
class Student:
school='yyds'
def say(self,school):
self.school=school
s1=Student()
s1.say('ohhh')
print(s1.school,Student.school)
以上的话我们运行可以发现,用s1得到的是ohhh,用Student得到是yyds,这里我们可以理解为局部变量的优先级大于全局变量,两者尽量不要有重名
此外,我们还可以修改或增加类对象与实例对象的属性,如下所示的代码:
class Student:
school='yyds'
def say(self,school):
self.school=school
s1=Student()
s1.say('ohhh')
s1.age=11
s1.name='小明'
Student.age=111
print(s1.age,s1.name,Student.age)
我们在这里对s1增加了age与name属性,对Student增加了age属性,输出的与增加的相同
要注意的一点是实例方法的第一个变量永远是self,其后面跟着定义的是其余的自定义的变量。
我们这里先说一种特殊的方法定义:对于__init__ 的重写,python在创建对象的时候默认是存在init的,但是如果我们想对初始化重新写的话,就可以加入一个对于以上__init__的重写,也可以带变量,但是在调用创建的时候也要带变量。
如下图代码所示:
class Student:
school='yyds'
def __init__(self):
self.name='111'
self.age=16
self.school='ohhh'
s1=Student()
print(s1.name,s1.age,s1.school)
这个是不带变量的,下面是输出:
class Student1:
school='yyds'
def __init__(self,name,age,school):
self.name=name
self.age=age
self.school=school
s2=Student1('yyds',16,'ohhh')
print(s2.school,s2.name,s2.age)
这是带变量的,下面是输出结果
当然也可以构造很多其他的方法,构造的形式和以上类似,但要注意的一点是第一个变量永远是 self
我们再来一个实例方法的例子
class Student:
student_num=0
def add(self,name):
print('增加了一名新同学,名字叫:%s'% name)
Student.student_num+=1
s1=Student()
s1.add('yyds')
print(s1.student_num)
s2=Student()
s2.add('ohhh')
print(s2.student_num)
我们可以看出来在一个代码中,每创建一个类属性,类变量不会清零,而是递加的
很简单,就是在方法的上面加上一个@classmethod,但是第一个变量是cls,类变量可以调用,通过cls可以访问相关的类属性,但是不能访问实例属性,如下面的代码所示:
class Student:
student_num=0
def add(self,name):
print('增加了一名新同学,名字叫:%s'% name)
Student.student_num+=1
@classmethod
def sub(cls,name):# 这里的cls只能访问类属性,不能访问实例属性
print('转走了一个学生,名字为:%s'% name)
cls.student_num-=1
s1=Student()
s1.add('yyds')
print(s1.student_num)
s2=Student()
s2.add('ohhh')
print(s2.student_num)
Student.sub('ohhh')
print(Student.student_num)
在程序的前面加一个@staticmethod
静态方法可以访问类属性,但不可以访问实例属性
class Student():
num=0
def __init__(self,myName):
Student.num+=1
self.name=myName
@staticmethod
def count():
print('学生个数:%d'%Student.num)
Student.count()
s1=Student('小千')
s1.count()
s2=Student('小峰')
s1.count()
下面是输出结果:
class MyComplex:
def __init__(self,r=0,i=0): # 构造方法
self.r=r
self.i=i
def __add__(self, other): # 重载乘运算
return MyComplex(self.r+other.r,self.i+other.i)
def __sub__(self, other): # 重载减运算
return MyComplex(self.r-other.r,self.i-other.i)
def __mul__(self, other): # 重载乘运算
return MyComplex(self.r*self.r,other.i*other.i)
def __truediv__(self, other): # 重载除运算
return MyComplex(
(self.r*other.r+self.i*other.i)/(other.r**2+other.i**2),
(self.i*other.r-self.r*other.i)/(other.r**2+other.i**2)
)
def show(self): # 设置输出的格式
if self.i<0:
print('(',self.r,self.i,'j',')',sep='')
else:
print('(',self.r,'+',self.i,'j',')',sep='')
c1=MyComplex(6,-8)
c2=MyComplex(1,-1)
(c1+c2).show()
(c1-c2).show()
(c1*c2).show()
(c1/c2).show()
下面是输出:
当对象作为str()或者print()的参数时,该对象会调用重载的__str__ 方法,所以我们在类中重载了str之后,该类加减的时候会直接返回我们定义的输出形式
class MyComplex:
def __init__(self,r=0,i=0):# 构造方法
self.r=r
self.i=i
def __str__(self):
if self.i<0:
return '('+str(self.r)+str(self.i)+'j)'
else :
return '('+str(self.r)+'+'+str(self.i)+'j)'
c1=MyComplex(6,-8)
c2=MyComplex(1,2)
print(c1,str(c2))
当对实例对象执行索引、分片或迭代时,该对象会调用__getitem__()方法
class Data:# 定义一个数据类
def __init__(self,list):
self.data=list[::-1]
def __getitem__(self, item): # 重载索引与分片
return self.data[item]
data=Data([1,2,3,4,5])
print(data[2])
print(data[1:])
for i in data:
print(i,end=' ')
用setitem来是实现对对象的修改
class Data:# 定义一个数据类
def __init__(self,list):
self.data=list[::-1]
def __setitem__(self, key,value): # 重载索引与分片
self.data[key]=value
data=Data([1,2,3,4,5])
print(data.data)
data.data[1]='千千万万'
data.data[2:]='you are a little cow horse'
print(data.data)
class Data:# 定义一个数据类
def __init__(self,list):
self.data=list[::-1]
def __contains__(self, item): # 重载索引与分片
return item in self.data
data=Data([1,2,3,4,5])
print(1 in data.data)
总结一下:重载就是先创建一个类,然后我们在里面定义重载的符号,我们在要建一个实例对象来表达我们要计算的数,然后实例对象之间的计算就是来根据重载符来计算的