python 面向对象 (我看看这咋回事儿
Python 面向对象 | 菜鸟教程 (runoob.com)
名词含义
- 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 相同属性+方法的对象集合
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。 类中所有实例都可使用,外部使用时为ClassName.LeiName
- 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
创建类
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#创建类
class Task:
'所有员工的基类' #类文档字符串
taskCount = 0
def __init__(self, id, name):
#__init__()是类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
#self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数
#类方法与普通函数只有一个区别:必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
self.name = name
self.id = id
Task.taskCount += 1
def displayCount(self):
print ("Total Task:" +Task.taskCount)
def displayTask(self):
print ("Name: "+self.name+", id: "+str(self.id))
"创建类的对象"
task1 = Task(1, "name1")
task2 = Task(2, "name2")
task1.displayTask()
task2.displayTask()
print ("Total task:"+str(Task.taskCount))
#类中添加属性
task1.status = "status1" #print(task1.status)
#类中修改属性值
task1.status = "new-status1" #print(task1.status)
#删除类的属性
del task1.status #print(task1.status) AttributeError: 'Task' object has no attribute 'status'
使用以下函数的方式来访问属性:
- getattr(obj, name[, default]) : 访问对象的属性。
- hasattr(obj,name) : 检查是否存在一个属性。
- setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
- delattr(obj, name) : 删除属性。
print(getattr(task1,"name")) #getattr() 返回task1的name值
print(hasattr(task1,"name")) #hasattr() 返回task1是否有name属性,有True无False
#setattr()设置taskx的某属性值,无属性则创建属性并赋值
setattr(task1,"name","new-name1") #print(task1.name)
setattr(task2,"status","status2") #print(task2.status)
#delattr() 删除taskx的某个属性
delattr(task2,"status") #print(task2.status)
内置类属性
_dict_ : 类的属性(包含一个字典,由类的数据属性组成)
_doc_ :类的文档字符串
_name_: 类名
_module_:
类定义所在的模块(类的全名是’__main__.className’,如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
_bases_ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)
print ("类属性dict:"+str(Task.__dict__))
print ("类文档字符串doc:"+str(Task.__doc__))
print ("类名name:"+str(Task.__name__))
print ("类所在模块module:"+str(Task.__module__))
print ("类的所有父类构成元素bases:"+str(Task.__bases__))
类的继承
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
class 子类名(父类名)
...
- 如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。python 子类继承父类构造函数说明。
- 在调用父类的方法时,需要加上父类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数
- Python 总是首先查找对应类型的方法,如果它不能在子类中找到对应的方法,它才开始到父类中逐个查找。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Task:
taskCount = 0
def __init__(self, id, name):
self.name = name
self.id = id
Task.taskCount += 1
def displayCount(self):
print ("Total Task:" +Task.taskCount)
def displayTask(self):
print ("Task类结果Name: "+self.name+", id: "+str(self.id))
def setname(self,name,id):
self.name = name
self.id = id
class Taskchild(Task): #定义bug是task的子类
def __init__(self):
print("zilei")
def gettask(self):
print("zilei")
task3 = Taskchild() #创建子类的实例,执行了init并输出zilei
task3.gettask()
task3.setname("name3",3) #子类没有setname方法去父类找
task3.displayTask()
还可以继承多个类
class A: # 定义类 A
.....
class B: # 定义类 B
.....
class C(A, B): # 继承类 A 和 B
.....
使用issubclass()或者isinstance()方法来检测
- issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)
- isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#创建类
class Task:
taskCount = 0
def __init__(self, id, name):
self.name = name
self.id = id
Task.taskCount += 1
task1 = Task(1, "name1")
task2 = Task(2, "name2")
class Taskchild(Task): #定义bug是task的子类
def __init__(self):
print("zilei")
task3 = Taskchild() #创建子类的实例,执行了init并输出zilei
print(issubclass(Task,Taskchild)) #Task是Taskchild的子类 false
print(issubclass(Taskchild,Task)) #Taskchild是Task是的子类 true
print(isinstance(task2,Taskchild)) #task2是Taskchild和其子类的实例 false
print(isinstance(task3,Task)) #task3是Task和其子类的实例 true
方法重写
父类方法不能满足子类使用 支持在子类中重写父类方法
子类中存在和父类某方法一样名称的方法,此方法仅在子类中生效
class Parent:
def __init__(self,x,y):
self.x = x
self.y = y
def method(self):
sum = self.x+self.y
print (sum)
class Child(Parent):
def __init__(self,x,y):
self.x = x
self.y = y
def method(self):
sum = self.x+self.y+self.y
print (sum)
task1 = Parent(1,2)
task1.method() #用的父类的method
task2 = Child(1,2)
task2.method() #子类中又method所以直接使用子类的
基础重载方法
序号 | 方法 | 描述 | 调用 |
---|---|---|---|
1 | _init_ ( self [,args…] ) | 构造函数 | obj = className(args) |
2 | _del_( self ) | 析构方法 , 删除一个对象 | del obj |
3 | _repr_( self ) | 转化为供解释器读取的形式 | repr(obj) |
4 | _str_( self ) | 用于将值转化为适于人阅读的形式 | str(obj) |
5 | _cmp_ ( self, x ) | 对象比较 | cmp(obj, x) |
class Parent:
def __init__(self,x,y):
self.x = x
self.y = y
#__init__
task1 = Parent(1,2)
#__del__ print (task1.x) AttributeError: 'Parent' object has no attribute 'x'
del task1.x
#__repr__
some_object = {'name': 'Alice', 'age': 30}
representation_string = repr(some_object)
print(representation_string)
# 输出: "{'name': 'Alice', 'age': 30}"
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})"
person = Person("Bob", 35)
print(repr(person)) # 输出: "Person(name='Bob', age=35)"
#str
#1.创建字符串
s1 = "Hello, World!" # 使用双引号创建字符串
s2 = 'This is also a string.' # 使用单引号创建字符串
s3 = """这是一个多行
字符串。""" # 使用三引号创建多行字符串
#2.访问字符串中的字
s = "hello"
print(s[0]) # 输出 'h'
print(s[-1]) # 输出 'o',负索引从末尾开始计数
#3.切片操作
print(s[1:4]) # 输出 'ell' 从index=1到index=4 包含1不包含4
#4.长度和计数
print(len(s)) # 输出 5,字符串长度
print(s.count('l')) # 输出2,指定字符在字符串中出现的次数
#5.字符串连接和重复
s4 = " " + s # 连接字符串
print(s4) # 输出 " hello"
s5 = s * 3 # 重复字符串
print(s5) # 输出 "hellohellohello"
#6.字符串格式化
name = "Alice"
age = 25
message = f"你好,{name},你今年{age}岁。"
print(message) # 输出 "你好,Alice,你今年25岁。"
#7.字符串方法
s6 = " Hello, World! "
trimmed_s6 = s6.strip() # 移除字符串两侧的空白字符
upper_s6 = s6.upper() # 将字符串转换为大写
lower_s6 = s6.lower() # 将字符串转换为小写
contains_world = "World" in s6 # 检查字符串是否包含子串
print(trimmed_s6, upper_s6, lower_s6, contains_world)
#cmp(x, y) x<y返回-1 x==y返回0 x>y返回1
运算符重载
#!/usr/bin/python
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2
#输出:Vector (7, 8)
类属性与方法
私有属性: __name
- 用两个下划线开头声明为私有
- 在类的外部不能使用,内部不能直接使用,内部需要使用 对象名._类名__私有属性名
类方法:def(self,…):
- 使用def定义方法
- 类方法必须包含参数self作为第一个参数
类的私有方法: __method
- 两个下划线开头声明私有
- 不能再类的外部调用,内部调用使用 self.__method
class Parent:
__sum = 10 #__sum私有变量,被使用需要self.__sum
def __init__(self,x,y):
self.x = x
self.y = y
def method(self):
self.__sum = self.__sum+self.x+self.y
print (self.__sum)
class Child(Parent):
def __init__(self,x,y):
self.x = x
self.y = y
def __method(self): #__method是私有方法,被使用需要task2._Child__method
sum = self.x+self.y+self.y
print (sum)
task1 = Parent(1,2)
task1.method()
task2 = Child(1,2)
task2._Child__method()
下划线
- __method__ 定义特殊方法,一般为系统方法
- _name 一个下划线开头,protected变量,仅支持本身和子类访问
- __name 两个下划线开头,private变量,仅允许本身访问