#类的定义与对象的创建
#example 1
class Person:
number=0 #类属性
def __init__(self,name,gender,age): #构造函数,创建对象时自动调用,用于初始化对象属性,通常self被指定为第一个参数,表示所创建的对象
self.name=name
self.gender=gender
self.age=age
Person.number+=1
def displayPerson(self): #方法定义,用于输出对象信息
print('Name:',self.name,'gender:',self.gender,'age:',self.age)
def displayNumber(self): #方法定义,用于打印生成对象个数,调用的是类属性number(感觉跟c++中的静态成员变量有点相同)
print('Total person:',Person.number)
stu1=Person('LiMing','M',19)
stu2=Person('LiLi','F',20) #创建对象,传入的参数要与构造函数参数对应
stu1.displayPerson() #通过对象调用实例方法,与c++差不多
stu2.displayPerson()
print("Total person:",Person.number) #通过类直接调用类属性
stu1.displayNumber() #通过对象方法显示类属性
print(stu2.number) #通过对象也可调用类属性
stu1.score=90 #有属性时更新其值,没有此属性时为对象创建该属性
stu2.score=80
print("LiMing's score:",stu1.score) #测试属性是否添加成功
print("LiLi's score:",stu2.score)
stu1.age=20 #修改已有属性age
print(stu1.age)
#del stu1.age #删除对象stu1的属性age
stu1.displayPerson() #如果上条代码成功执行,则这条语句就会报错,因为方法displayPerson()中会找不到age属性
print(hasattr(stu2,'score')) #若对象有该属性(attr是attribute缩写),则返回True,否则返回False
print(getattr(stu2,'score')) #返回该对象的该属性值
setattr(stu2,'score',100) #设置对象的属性值,若该对象有此属性,则更新其值。若无此属性,则添加该属性并设置其属性值
setattr(stu2,'money',1)
#下面四条语句是用来测试上述语句是否设置成功
print(stu2.money) #测试属性money是否设置成功
print(getattr(stu2,'score')) #测试属性score是否设置成功
delattr(stu2,'score') #删除属性score
print(hasattr(stu2,'score')) #测试属性是否删除成功
'''
运行结果:
Name: LiMing gender: M age: 19
Name: LiLi gender: F age: 20
Total person: 2
Total person: 2
Total person: 2
LiMing's score: 90
LiLi's score: 80
20
Name: LiMing gender: M age: 20
True
80
1
100
False'''
#属性和方法
#example 2
'''
属性分为类属性和对象属性
类属性:在类中方法之外定义的属性,可看做公有财产,既可通过类名访问,也可通过对象名访问Person.number和stu1.number均可
对象属性:在构造函数或类外定义,只为特定对象所拥有,故只能通过对象名访问,如Person.name就不会成功执行
公有属性,私有属性:以命名方式区别,私有属性以__(双下划线)开头
__number=0 #私有类属性 self.__age=age #私有对象属性
Person._Person__number #调用私有类属性 stu1._Person__age #调用私有对象属性'''
class classname:
public_classattr=0 #公有类属性
__private_classattr=1 #私有类属性
def __init__(self,public_objattr,private_objattr):
self.public_objattr=public_objattr #公有对象属性
self.__private_objattr=private_objattr #私有对象属性
class1=classname(2,3)
print("公有类属性:",classname.public_classattr) #类属性用类名访问
print("私有类属性:",classname._classname__private_classattr) #私有的在属性前面加_类名
print("公有对象属性:",class1.public_objattr) #对象属性用对象访问
print("私有对象属性:",class1._classname__private_objattr)
'''
运行结果
公有类属性: 0
私有类属性: 1
公有对象属性: 2
私有对象属性: 3'''
#对象方法,类方法,静态方法,内置方法(构造和析构)
#example 3
'''对象方法包括公有方法和私有方法
公有方法:既可以通过类名调用,也可以通过对象名调用。但是用类名调方法时必须传入一个对象
私有对象:可以通过类名或对象名调用,也可以通过对象的公有方法调用私有方法
'''
class Methods:
def publicMethod1(self):
print("公有方法publicMethod!")
def __privateMethod(self):
print("私有方法privateMethod!")
def publicMethod2(self):
self.__privateMethod() #在对象的共有方法中用self调用对象的私有对象
m=Methods()
m.publicMethod1() #通过对象调用公有方法
Methods.publicMethod1(m) #通过类调用公有方法,需要传入一个对象
m._Methods__privateMethod() #通过对象调用私有方法,在私有方法前要加‘_类名’
Methods._Methods__privateMethod(m) #通过类调用私有方法
m.publicMethod2() #通过公有方法调用私有方法
'''
运行结果
公有方法publicMethod!
公有方法publicMethod!
私有方法privateMethod!
私有方法privateMethod!
私有方法privateMethod!'''
#example 4
#类方法和静态方法
class method:
@classmethod #用修饰器@classmethod来定义类方法
def publicClassMethod(cls): #定义类方法时用cls作为第一个参数名称,在调用时不需要为该参数传递值
print("公有类方法publicClassMethod!")
@classmethod
def __privateClassMethod(cls): #一旦定义的是私有方法,要记得双下划线开头
print("私有类方法privateClassMethod!")
@staticmethod
def publicStaticMethod(): #用修饰器@staticmethod来定义类方法
print("公有静态方法publicStaticMethod!") #定义静态方法时无需传入self参数或cls参数
@staticmethod
def __privateStaticMethod():
print("私有静态方法privateStaticMethod!")
def publicMethod(self):
print("普通公有方法publicMethod!") #定义普通方法时用self作为第一个参数名称代表对象,在调用时不需要为该参数传递值
def __privateMethod(self):
print("普通私有方法privateMethod!")
publicMethodToClassMethod=classmethod(publicMethod) #用内置函数classmethod()将普通方法转为类方法
privateMethodToClassMethod=classmethod(__privateMethod)
publicMethodToStaticMethod=staticmethod(publicMethod) #用内置函数staticmethod()将普通方法转为静态方法
privateMethodToStaticMethod=staticmethod(__privateMethod)
m=method()
m.publicClassMethod() #可用对象名和类名访问公有类方法
method.publicClassMethod()
m._method__privateClassMethod() #可用对象名和类名访问私有类方法
method._method__privateClassMethod()
m.publicMethodToClassMethod() #访问转换的类方法
method.publicMethodToClassMethod()
m.privateMethodToClassMethod()
method.privateMethodToClassMethod()
m.publicStaticMethod() #可用对象名和类名访问公有静态方法
method.publicStaticMethod()
m._method__privateStaticMethod() #可用对象名和类名访问私有静态方法
method._method__privateStaticMethod()
m.publicMethodToStaticMethod(m) #访问转换的静态方法,但调用时必须传入一个对象
method.publicMethodToStaticMethod(m)
m.privateMethodToStaticMethod(m)
method.privateMethodToStaticMethod(m)
'''
运行结果
公有类方法publicClassMethod!
公有类方法publicClassMethod!
私有类方法privateClassMethod!
私有类方法privateClassMethod!
普通公有方法publicMethod!
普通公有方法publicMethod!
公有静态方法publicStaticMethod!
公有静态方法publicStaticMethod!
私有静态方法privateStaticMethod!
私有静态方法privateStaticMethod!
普通公有方法publicMethod!
普通公有方法publicMethod!
普通私有方法privateMethod!
普通私有方法privateMethod!'''
#example 5
#内置方法
#这里只看比较重要的构造函数和析构函数
'''构造函数见example 1中的__init__(self,...)函数
析构函数见__del__(self),调用方法:del obj_name
对象创建时自动调用构造函数,用来为对象分配内存并对属性进行初始化
对象删除时自动调用析构函数,用来收回对象占用的存储空间
构造函数和析构函数均可以由用户自己定义,用户有对其定义时,按照用户所定义的运行
用户没有对其定义时,调用默认的内置函数'''
#example 6
#继承
#内置函数super()的使用,当继承关系发生改变时,只需改变基类名称,这样可以降低代码的维护量
class Person:
def __init__(self,name,gender,age): #构造函数,创建对象时自动调用,用于初始化对象属性,通常self被指定为第一个参数,表示所创建的对象
self.name=name
self.gender=gender
self.age=age
def display(self): #方法定义,用于输出对象信息
print('Name:',self.name,'gender:',self.gender,'age:',self.age)
class Student(Person):
def __init__(self,name,gender,age,no,major):
super(Student,self).__init__(name,gender,age) #用super(派生类,self)当作基类,调用基类的构造函数
self.no=no
self.major=major
def displayStudent(self):
print('number:',self.no,'major:',self.major)
super(Student,self).display() #用super调用基类的display()方法
stu1=Student('张明','男',19,'20190901','计算机系')
stu2=Student('张丽','女',20,'20190902','物理系')
stu1.displayStudent()
stu2.displayStudent()
'''
运行结果
number: 20190901 major: 计算机系
Name: 张明 gender: 男 age: 19
number: 20190902 major: 物理系
Name: 张丽 gender: 女 age: 20'''
#example 7
#多态(多态指基类的同一个方法在不同的派生类中具有不同的表现和行为,即派生类可能对基类的一些行为进行改变)
#方法重载
class Animal():
def display(self):
print('I am an animal.') #三个派生类cat,dog,wolf均继承与基类Animal
class Dog(Animal):
def display(self):
print('I am a dog.') #每个派生类中display()方法都覆盖了基类中的display()
class Cat(Animal):
def display(self):
print('I am a cat.')
class Wolf(Animal):
def display(self):
print('I am a wolf.')
x=[item() for item in (Animal,Dog,Cat,Wolf)]
for item in x:
item.display()
'''
运行结果
I am an animal.
I am a dog.
I am a cat.
I am a wolf.'''
#运行符重载
class number():
def __init__(self,a,b):
self.a=a
self.b=b
def __add__(self,x): #重载了+,-两个运算符,使其作用域不仅在基本类型,而延伸到类
return number(self.a+x.a,self.b+x.b) #这里的self为第一操作数,x为第二操作数
def __sub__(self,x):
return number(self.a-x.a,self.b-x.b)
n1=number(10,20)
n2=number(100,200)
m=n1+n2
n=n2-n1
print(m.a,m.b) #110 220
print(n.a,n.b) #90 180
#example 8
#异常处理
#try...except...
a=[1,2,3,4,5]
try:
print(a[5]) #待检测的程序代码
except IndexError: #IndexError是异常类型:索引下表出界的意思,这个是由计算机所报出的错误[IndexError: list index out of range]
print('索引下标出界') #此题输出:索引下标出界
#try...except...else...finally
while True:
try:
x=int(input("请输入数据1:"))
y=int(input("请输入数据2:"))
z=x/y
except ValueError: #传入参数错误
print("应全部输入数值数据!")
except ZeroDivisionError: #除零错误
print("除数不能为零!")
except NameError: #变量未定义错误
print("变量不存在!")
else:
print("最终结果为:",z)
finally:
print("END")
print("-----------------------------------------")
'''
运行结果
请输入数据1:3
请输入数据2:a
应全部输入数值数据!
END
-----------------------------------------
请输入数据1:5
请输入数据2:0
除数不能为零!
END
-----------------------------------------
请输入数据1:8
请输入数据2:2
最终结果为: 4.0
END'''
#example 9
#断言与上下文管理语句
try:
x=input("请输入数据1:")
y=input("请输入数据2:")
s="两次输入的数据不相等"
assert x==y,s
except AssertionError: #断言即是条件表达式,表达式为真,不执行任何操作;表达式为假,抛出断言错误
print(s)
'''
请输入数据1:abc
请输入数据2:abc
>>>
请输入数据2:a2c
两次输入的数据不相等'''