网站要和别人做api 链接,徐州徐州网站建设,用wp系统做网站,建设局网站招聘目录
一.类和类的实例
二.类属性和实例属性
三.私有属性和公有属性
四.静态方法和类方法 五.__init__方法#xff0c;__new__方法和__del__方法#xff1a;
六.私有方法和公有方法
七.方法的重载
八.方法的继承
九.方法的重写
十.对象的特殊方法
十一.对象的引用__new__方法和__del__方法
六.私有方法和公有方法
七.方法的重载
八.方法的继承
九.方法的重写
十.对象的特殊方法
十一.对象的引用浅拷贝和深拷贝 一.类和类的实例
类(Class):用来描述具有相同的属性和方法的对象的集合。定义了该集合中每个对象所共有的属性和方法。
类的实例每个对象都属于特定的类并被称为该类的实例(类的具体实体)。
看点实际的
class Person1: #定义类Person1pass # 类体为空语句
print(Person1, type(Person1), id(Person1))结果
class __main__.Person1 class type 2077119090192
Person1表示类对象的名称属于__main__模块
type(Person1):表示Person1一个类
id(Person1)表示Person1类的唯一标识符用来区别其他对象
class Person1: #定义类Person1pass # 类体为空语句
p1 Person1() #实例化该类并创建一个对象p1
print(p1, type(p1), id(p1))结果
__main__.Person1 object at 0x0000026DD4176DD0 class __main__.Person1 2670732996048
p1:p1是Person1类的一个对象属于“__main__”模块其内存地址为0x0000026DD4176DD0
type(p1):表示p1所属的类是Person1属于“__main__”模块
id(p1):表示p1对象的唯一标识符 二.类属性和实例属性
类变量属性:类变量在整个实例化的对象中是公用的,定义在类中且在函数体之外通常不作为实例变量使用,属于类本身可以通过类名访问/修改
class Person2:count 0 #定义属性count表示计数name Person #定义属性name表示名称def __init__(self):passdef fun(self):pass
#测试代码
Person2.count 1 #通过类名访问计数加1
print(Person2.count) #类名访问读取并显示类属性
print(Person2.name) #类名访问读取并显示类属性结果:
1
Person实例变量在类的声明中属性是用变量来表示的定义在方法内比如定义到构造方法中普通的方法内通过self.变量名定义的属性。
class Person3: #定义类Person3def __init__(self, name,age): #__init__方法self.name name #初始化self.nameself.age age #初始化self.agedef say_hi(self): #定义类Person3的函数say_hi()print(您好, 我叫, self.name)
#测试代码
p1 Person3(张三,25) #对象实例化
p1.say_hi () #调用对象的方法
print(p1.age) #通过p1.ageobj1.变量名读取成员变量age结果:
您好我叫张三
25
改变类属性值或实例变量值
class Person4:count 0 #定义属性count表示计数name Person #定义属性name表示名称
#测试代码
p1 Person4() #创建实例对象1
p2 Person4() #创建实例对象2
print((p1.name, p2.name)) #通过实例对象访问实例变量
Person4.name 雇员 #通过类变量访问设置类属性值
print((p1.name, p2.name)) #读取实例变量
p1.name 员工 #通过实例变量访问设置实例变量的值
print((p1.name, p2.name)) #读取实例变量的值结果 三.私有属性和公有属性
Python类的成员没有访问控制限制
约定两个下划线开头但不以两个下划线结束的属性是私有的private其他为公共的public
class A:def __init__(self):self.__name class A #私有类属性def get_name(self):print(self.__name) #在类方法中访问私有类属性
#测试代码
Aa A()
Aa.get_name()
Aa.__name #导致错误不能直接访问私有类属性结果 property
面向对象程序设计的封装性原则要求不直接访问类中的数据成员property装饰器装饰访问私有属性的方法使访问方式更友好。
class Person1:def __init__(self, name):self.__name namepropertydef name(self):return self.__name
#测试代码
p Person1(王五)
print(p.name)结果
王五property装饰器默认提供一个只读属性可使用对应的getter、setter和deleter装饰器实现其他访问器函数property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用这样可以防止属性被修改。
class Person12:def __init__(self, name):self.__name namepropertydef name(self):return self.__namename.setterdef name(self, value):self.__name valuename.deleterdef name(self):del self.__name
#测试代码
p Person12(姚六)
p.name 王依依
print(p.name)结果
王依依
property的调用格式 property(fgetNone, fsetNone, fdelNone, docNone) #fget为get访问器fset为set访问器fdel为del访问器 class Person1:def __init__(self, name):self.__name namedef getname(self):return self.__namedef setname(self, value):self.__name valuedef delname(self):del self.__namename property(getname, setname, delname, Im the name property.)
#测试代码
p Person1(张三)
print(p.name)
p.name 李四
print(p.name)结果
张三
李四
Python对象包含许多以双下划线开始和结束的变量称为特殊属性
特殊方法含义示例object.__dict__对象的属性字典int.__dict__ #mappingproxy({__new__: built-in method __new__...instance.__class__对象所属的类i.__class__ #class ‘int’int.__class__ #class ‘type’class.__bases__类的基类元组int.__bases__ #(class ‘object’)class.__base__类的基类int.__base__ #class ‘object’class.__name__类的名称int.__name__ # ‘int’class.__qualname__类的限定名称int.__qualname__ #’int’class.__mro__查看继承关系基类元组int.__mro__ #(class ‘int’, class ‘object’)class.mro()同上可被子类重写int.mro()#[class ‘int’, class ‘object’]class.__subclasses__()子类列表int.__subclasses__()#[class ‘bool’,enum ‘IntEnum’,...
自定义属性
对象可以通过特殊属性__dict__存储自定义属性
class C1:pass
oC1()
o.namecustom name
print(o.__dict__)
结果 拦截属性的访问 可通过重载__getattr__和__setattr__拦截对成员的访问从而自定义属性的行为
__getattr__只有在访问不存在的成员时才会调用
__getattribute__拦截所有包括不存在的成员的获取操作
注意不要使用return self.__dict__[name]返回结果因为self.__dict__[name]同样会被__getattribute__拦截造成无限递归死循环 __getattr__(self, name) #获取属性比__getattribute__()优先调用 __getattribute__(self, name)# 获取属性 __setattr__(self, name, value)#设置属性 __delattr__(self,name) #删除属性 class CustomAttribute(object):def __init__(self): #__init__方法构造函数pass #空语句def __getattribute__(self, name): #获取属性拦截所有的获取操作return str.upper(object.__getattribute__(self, name))#转换为大写def __setattr__(self, name, value): #设置属性object.__setattr__(self, name, str.strip(value))#去除收尾空格
#测试代码
o CustomAttribute() #创建实例对象
o.firstname mary #设置成员变量的值
print(o.firstname) # 读取并显示成员变量的值结果 四.静态方法和类方法
静态方法
•声明与类的对象实例无关的方法
•静态方法不对特定实例进行操作访问对象实例会导致错误
•静态方法通过装饰器staticmethod来定义
•静态方法一般通过类名来访问也可以通过对象实例调用
静态方法的声明和调用 #声明 staticmethod def 静态方法名[形参列表] 函数体 #调用 类名.静态方法名([实参列表]) class TemperatureConverter:staticmethoddef c2f(t_c): #摄氏温度到华氏温度的转换t_c float(t_c)t_f (t_c * 1.8) 32return t_fstaticmethoddef f2c(t_f): #华氏温度到摄氏温度的转换t_f float(t_f)t_c (t_f - 32) /1.8return t_c
#测试代码
print(1. 从摄氏温度到华氏温度.)
print(2. 从华氏温度到摄氏温度.)
choice int(input(请选择转换方向))
if choice 1:t_c float(input(请输入摄氏温度 ))t_f TemperatureConverter.c2f(t_c)print(华氏温度为 {0:.2f}.format(t_f))
elif choice 2:t_f float(input(请输入华氏温度 ))t_c TemperatureConverter.f2c(t_f)print(摄氏温度为 {0:.2f}.format(t_c))
else:print(无此选项只能选择1或2)
类方法
•Python允许声明属于类本身的方法即类方法
•类方法不对特定实例进行操作访问对象实例会导致错误
•类方法通过装饰器classmethod来定义
•第一个形式参数必须为类对象本身通常为cls
类方法的声明和调用 #声明 classmethod def 类方法名(cls,[形参列表]) 函数体 #调用 类名.类方法名[实参列表] class Foo:classname Foodef __init__(self, name):self.name namedef f1(self): #实例方法print(self.name)staticmethoddef f2(): #静态方法print(static)classmethoddef f3(cls): #类方法print(cls.classname)
#测试代码
f Foo(李)
f.f1()
Foo.f2()
Foo.f3()结果 五.__init__方法__new__方法和__del__方法
•__init__方法即构造函数构造方法用于执行类实例的初始化。创建完对象后调用初始化当前对象的实例无返回值
•__new__方法是一个类方法创建对象时调用返回当前对象的一个实例一般无需重载该方法
#__init__方法
class Point:def __init__(self, x 0, y 0): #构造函数self.x xself.y y
p1 Point() #创建对象
print(p1({0},{1}).format(p1.x, p1.y))
p1 Point(5, 5) #创建对象
print(p1({0},{1}).format(p1.x, p1.y))结果
p1(0,0)
p1(5,5)•__del__方法
__del__方法即析构函数析构方法用于实现销毁类的实例所需的操作如释放对象占用的非托管资源例如打开的文件、网络连接等
默认情况下当对象不再被使用时__del__方法运行由于Python解释器实现自动垃圾回收即无法保证这个方法究竟在什么时候运行
通过del语句可以强制销毁一个对象实例从而保证调用对象实例的__del__方法
class Person:count 0 #定义类域count表示计数def __init__(self, name,age): #构造函数self.name name self.age age Person.count 1 #创建一个实例时计数加1def __del__(self): #析构函数Person.count - 1 #销毁一个实例时计数减1def get_count(): #定义类Person的方法get_count()print(总计数为, Person.count)
print(总计数为,Person.count) #类名访问
p1 Person(张三,25) #创建对象
Person.get_count() #通过类名访问
p2 Person(李四,28) #创建对象
Person.get_count() #通过类名访问
del p1 #删除对象p1
Person.get_count() #通过类名访问
del p2 #删除对象p2
Person.get_count() #通过类名访问结果 六.私有方法和公有方法
•两个下划线开头但不以两个下划线结束的方法是私有的private其他为公共的public
•以双下划线开始和结束的方法是Python的专有特殊方法。
•不能直接访问私有方法但可以在其他方法中访问
class Book:def __init__(self, name, author, price):self.name nameself.author authorself.price pricedef __check_name(self): #定义私有方法判断name是否为空if self.name : return Falseelse: return Truedef get_name(self): #定义类Book的方法get_nameif self.__check_name():print(self.name,self.author) #调用私有方法else:print(No value)
b Book(Python语言程序设计,嵩天,50.0) #创建对象
b.get_name() #调用对象的方法
b.__check_name()
结果 七.方法的重载
•其他程序语言方法可以重载即定义多个重名的方法而方法签名唯一方法名、参数数量和参数类型
•Python本身是动态语言方法的参数没有声明类型在调用传值时确定参数的类型参数的数量可变。故Python对象方法不需要重载定义一个方法即可实现多种调用从而实现相当于其他程序设计语言的重载功能
class Person21: #定义类Person21def say_hi(self, nameNone): #定义类方法say_hiself.name name if nameNone: print(您好! )else: print(您好, 我叫, self.name)
p21 Person21() #创建对象
p21.say_hi() #调用对象的方法无参数
p21.say_hi(威尔逊) #调用对象的方法带参数结果 再看以下代码
在Python类体中可以定义多个重名的方法虽然不会报错但只有最后一个方法有效所以建议不要定义重名的方法
class Person22:def say_hi(self, name): #带两个参数print(您好, 我叫, self.name)def say_hi(self, name, age): #带三个参数print(hi, {0}, 年龄{1}.format(name,age))
p22 Person22() #创建对象
p22.say_hi(Lisa, 22) #调用对象的方法
p22.say_hi(Bob) # error结果 八.方法的继承
•派生类Python支持多重继承即一个派生类可以继承多个基类
•如果类定义中没有指定基类默认基类为object。object是所有对象的根基类
•声明派生类时必须在其构造函数中调用基类的构造函数
派生类的声明和调用 #声明 class 派生类名(基类1,[基类2...]): 类体 #调用 基类名.__init__(self, 参数列表) 或者 super().__init__(参数列表) class Person: #基类def __init__(self, name, age): #构造函数self.name nameself.age agedef say_hi(self): #定义基类方法say_hiprint(您好, 我叫{0}, {1}岁.format(self.name, self.age))
class Student(Person): #派生类def __init__(self, name, age, stu_id): #构造函数Person.__init__(self, name, age) #调用基类构造函数self.stu_id stu_id #学号def say_hi(self): #定义派生类方法say_hiPerson.say_hi(self) #调用基类方法say_hiprint(我是学生, 我的学号为, self.stu_id)
p1 Person(张王一, 33) #创建对象
p1.say_hi()
s1 Student(李姚二, 20, 2018101001) #创建对象
s1.say_hi()结果 通过类的方法mro()或类的属性__mro__可以输出其继承的层次关系 class A: pass class B(A):pass class C(B):pass class D(A):pass class E(B,D):pass D.mro() [class __main__.D, class __main__.A, class object] E.__mro__ (class __main__.E, class __main__.B, class __main__.D, class __main__.A, class object) 九.方法的重写
通过继承派生类继承基类中除构造方法之外的所有成员如果在派生类中重新定义从基类继承的方法则派生类中定义的方法覆盖从基类中继承的方法
class Dimension: #定义类Dimensionsdef __init__(self, x, y): #构造函数self.x x #x坐标self.y y #y坐标def area(self): #基类的方法area()pass
class Circle(Dimension): #定义类Circle圆def __init__(self, r): #构造函数Dimension.__init__(self, r, 0)def area(self): #覆盖基类的方法area()return 3.14 * self.x * self.x #计算圆面积
class Rectangle(Dimension): #定义类Rectangle矩形def __init__(self, w, h): #构造函数Dimension.__init__(self, w, h)def area(self): #覆盖基类的方法area()return self.x * self.y #计算矩形面积
d1 Circle(2.0) #创建对象圆
d2 Rectangle(2.0, 4.0) #创建对象矩形
print(d1.area(), d2.area()) #计算并打印圆和矩形面积结果 十.对象的特殊方法
特殊方法含义__lt__、__add__等对应运算符,等__init__、__del__创建或销毁对象时调用__len__对应内置函数len()__setitem__、__getitem__按索引赋值、取值__repr__(self)对应于内置函数repr()__str__(self)对应于内置函数str()__bytes__(self)对应于内置函数bytes()__format__(self,format_spec)对应于内置函数format()__bool__(self)对应于内置函数bool()__hash__(self)对应于内置函数hash()__dir__(self)对应于内置函数dir()
对象的特殊方法实例
class Person:def __init__(self, name, age): #特殊方法构造函数self.name nameself.age agedef __str__(self): #特殊方法return {0}, {1}.format(self.name,self.age)def __repr__(self): #特殊方法return {},{}.format(李四,24)
#测试代码
p1 Person(张三, 23)
print(p1)
print(repr(p1))结果
张三23
李四24运算符的重载与对象的特殊方法
Python的运算符实际上是通过调用对象的特殊方法实现的
运算符特殊方法含义,,,,,! __lt__(),__le__(),__eq__(),__gt__() ,__ge__(),__ne__() 比较运算符|,^, __or__(),__ror__(),__xor__(), __rxor__(),__and__(),__rand__() 按位或、异或、与|,^,__ior__(),__ixor__(),__iand__()按位复合赋值运算,__lshift__(),__rlshift__(),__rshift__(),__rrshift__()移位运算,__ilshift__(),__irlshift__(),__irshift__(),__irrshift__()移位复合赋值运算,-__add__(),__radd__(),__sub__(),__rsub__()加法与减法,-__iaddr__(),__isub__()加减复合赋值运算*,/,%,// __mul__(),__rmul__(),__truediv__(),__rtruediv__(), __mod__(),__rmod__(),__floordiv__(),__rfloordiv__() 乘、除、取余、整数除法*,/,%.// __imul__(),__idiv__(),__itruediv__(),__imod__(),__ifloordiv__() 乘除复合赋值运算x,-x__pos__(),__neg__()正负号~x__invert__()按位翻转**, **__pow__(),__rpow__(),__ipow__()指数运算
示例
class MyList():def __init__(self, *args):self.__mylist [] #初始化私有属性空列表for i in args:self.__mylist.append(i)def __add__(self, other): #重载运算符每个元素增加nfor i in range(len(self.__mylist)):self.__mylist[i] otherdef __sub__(self, other): #重载运算符-每个元素减少nfor i in range(len(self.__mylist)):self.__mylist[i] - otherdef __mul__(self, other):for i in range(len(self.__mylist)):self.__mylist[i] * otherdef __truediv__(self, other):for i in range(len(self.__mylist)):self.__mylist[i] / otherdef __len__(self):return len(self.__mylist)def __repr__(self):str1 for i in range(len(self.__mylist)):str1 str(self.__mylist[i]) return str1
alist MyList(1,2,3,4,5);
alist 2;
print(repr(alist));
alist - 1;
print(repr(alist));
alist * 2;
print(repr(alist));
alist/2;print(repr(alist));
print(len(alist))functools.total_ordering
支持大小比较的对象需要实现特殊方法__eq__、__lt__、__le__、__ge__、__gt__,但使用functools模块的total_ordering装饰器装饰类则只需要实现__eq__以及__lt__、__le__、__ge__、__gt__中的任意一个
import functools
functools.total_ordering
class Student:def __init__(self, firstname, lastname): #姓和名self.firstname firstnameself.lastname lastnamedef __eq__(self, other): #判断姓名是否一致return ((self.lastname.lower(), self.firstname.lower()) (other.lastname.lower(), other.firstname.lower()))def __lt__(self, other): #self姓名other姓名return ((self.lastname.lower(), self.firstname.lower()) (other.lastname.lower(), other.firstname.lower()))
#测试代码
if __name__ __main__:s1 Student(Mary,Clinton)s2 Student(Mary,Clinton)s3 Student(Charlie,Clinton)print(s1s2)print(s1s3)print(s1s3)结果 __call__方法
__call__方法的对象称之为可调用对象callable即该对象可以像函数一样被调用
class GDistance: #类自由落体距离def __init__(self, g): #构造函数self.g g def __call__(self, t): #自由落体下落距离return (self.g*t**2)/2
#测试代码
if __name__ __main__:e_gdist GDistance(9.8) #地球上的重力加速度for t in range(11): #自由落体0~10秒的下落距离print(下落距离为{:0.2f}m.format(e_gdist(t))) 结果 十一.对象的引用浅拷贝和深拷贝
对象的引用在创建一个对象并赋值给一个变量时该变量是指向该对象的引用其id()返回值保持一致 acc10[Charlie, [credit, 0.0]]
#创建列表对象信用卡账户变量acc10代表主卡acc11acc10
#变量acc11代表副卡指向acc10主卡的对象id(acc10),id(acc11)
#二者id相同输出
(2739033039112, 2739033039112)对象的浅拷贝
对象的拷贝可以使用以下方法 切片操作例如acc11[:]。 对象实例化例如list(acc11)。 copy模块的copy函数例如copy.copy(acc1)。 import copy
acc1[Charlie,[credit,0.0]]
acc2acc1[:] #使用切片方式拷贝对象
acc3list(acc1) #使用对象实例化方法拷贝对象
acc4copy.copy(acc1) #使用copy.copy函数拷贝对象
print(id(acc1),id(acc2),id(acc3),id(acc4)) #拷贝对象id各不相同
acc2[0]Mary #acc2的第一个元素赋值即户主为Mary
acc2[1][1]-99.9 #acc2的第二个元素的第二个元素赋值即消费金额99.9
print(acc1, acc2) #注意acc2消费金额改变99.9acc1也随之改变
结果 对象的深拷贝
Python复制一般为浅拷贝即复制对象时对象中包含的子对象并不复制而是引用同一个子对象。如果要递归复制对象中包含的子对象需使用深拷贝
深拷贝需要使用copy模块的deepcopy函数拷贝对象中包含的子对象 acc5[0]Clinton #acc5的第1个元素赋值即户主为Clinton acc5[1][1]-19.9 #acc5的第2个元素的第2个元素赋值即消费金额19.9 acc1,acc5 ([Charlie, [credit, 0.0]], [Clinton, [credit, -19.9]]) id(acc1),id(acc5),id(acc1[1]),id(acc5[1]) (2739033040648, 2739033040264, 2739033040520, 2739033039688)