Python 深入浅出
来源:互联网 发布:wepy 知乎 编辑:程序博客网 时间:2024/06/05 23:43
Python 面向对象
在 Python 中,所有的数据类型都可以视为对象,当然也可以自定义对象,自定义对象数据类型就是面向对象中的类 Class 的概念。
- 类:用来描述具有相同属性和方法的对象的集合,它定义了该集合中每个对象的共有的属性和方法。
- 类变量:类变量在整个实例化的对象中是公有的,类变量定义在类中且在函数体外。
- 实例变量:定义在方法中的变量,只能作用于当前实例。
- 实例化:即创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。
创建类
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾。
class ClassName: '类的帮助信息' #类文档信息 类变量 方法 数据属性
例子:
class Employee(object): 'Employee 雇员类' empCount = 1 # 类变量 def __init__(self, name, age): self.__name = name # 实例变量 self.__age = age # 实例变量 def printCount(self): print("Total employee = %d" % Employee.empCount) def printEmployee(self): print("name = %s ,age = %d" % (self.__name, self.__age))
- 类名后面的 (object) 表示这个类是从哪个类继承下来的, object 是所有类的父类。
- _ init_() 方法是是类的构造函数或初始化方法,当创建类的实例时就会调用这个方法。
- self 代表类的实例,self 参数在定义类的方法时必须有的,在创建实例时,self 参数不需要传入,解释器自己会把实例变量传进去。
- 实例变量在变量名前面加上两个下划线就变成了一个私有变量,只有类内部可以访问,外部不能访问;这样确保外部代码不能随意修改对象内部的属性的值。双下划线的变量不能再类外直接访问,是因为解释器对外把 __name 变量改成了 _Person__name ,所以,任然可以通过 _Student__name 来访问 __name 变量。
- 同时,可以给类定义get ,set 方法,用于获取和修改类的属性。
创建实例对象
创建实例使用 类名(参数…),其中参数对应于定义类时的 init 方法中的参数。
e = Employee("tomcat",22)e.printCount()e.printEmployee()
输出结果:
Total employee = 1
name = tomcat ,age = 22
Python 内置类属性
- _ dict _:类的属性,由类的数据属性组成
- _ doc _:类的文档字符串
- _ name _:类名
- _ module _:类定义所在的模块
- _ bases _:类的所有父类构成元素
print("Employee.__doc__:",Employee.__doc__)print("Employee.__name__:",Employee.__name__)print("Employee.__module__:",Employee.__module__ )print("Employee.__bases__:",Employee.__bases__)print("Employee.__dict__:",Employee.__dict__)
输出结果:
Employee.doc: Employee 雇员类
Employee.name: Employee
Employee.module: main
Employee.bases: (<class ‘object’>,)
Employee.dict: {‘module‘: ‘main‘, ‘doc‘: ‘Employee 雇员类’, ‘empCount’: 1, ‘init‘: <function Employee.init at 0x0175F780>, ‘printCount’: <function Employee.printCount at 0x0175F5D0>, ‘printEmployee’: <function Employee.printEmployee at 0x0175F588>, ‘dict‘: <attribute ‘dict’ of ‘Employee’ objects>, ‘weakref‘: <attribute ‘weakref’ of ‘Employee’ objects>}
继承
语法: class 派生类名(基类名):
基类:
class Animal(object): def run(self): print("Animal run.....")
子类:
class Dog(Animal): passclass Cat(Animal): passdog = Dog()cat = Cat()dog.run()cat.run()
输出结果:
Animal run…..
Animal run…..
子类自动继承了父类中方法。
注意:
1. 在继承中基类的构造(init() 方法) 不会被自动调用,需要在其派生类的构造中亲自专门调用。
2. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量,区别在于类中调用普通函数时,并不需要带上 self 参数。
3. Python 总是首先查找对应类型的方法,如果他不能再派生类中找到对应的方法,他才开始到基类中逐个查找。
方法覆盖
class Dog(Animal): def run(self): print("Dog run....")class Cat(Animal): def run(self): print("Cat run....")dog = Dog()cat = Cat()dog.run()cat.run()
输出结果:
Dog run….
Cat run….
当子类和父类都存在相同的方法时,子类方法覆盖了父类的方法,在代码执行时,调用的是子类中的那个方法。
多态
def run_animal(animal): animal.run()run_animal(dog)run_animal(cat)
输出结果:
Dog run….
Cat run….
可见,Animal类型的参数,可以传入 Dog,Cat 类型变量,只有传入的参数类型是 Animal 的子类,都可以接收。
鸭子模型
对于静态语言(Java)来说,如果需要传入 Animal 类型,则传入的对象必须是 Animal 类型或者他的子类,否则,将无法调用 run() 方法。但是,对用 Python 这种动态语言来说,则不一定需要传入 Animal 类型,只需保证传入的对象有一个 run() 方法即可。
type() 获取对象信息
使用 type() 函数可以判断出对象的类型。
print(type(123))print(type("123"))print(type(None))print(type([1,2,3]))print(type((1,2,3)))print(type({"Android":"Google","iOS":"Apple"}))print(type(True))print(type(abs)) # abs 绝对值,内置函数print(type(dog))
输出结果:
判断对象是否是函数
import typesdef function_add(): passfunction_res = type(function_add) == types.FunctionTypeprint(function_res)
输出结果: True
对象是否是类的实例 - isinstance()
print("dog is Animal = " , isinstance(dog,Animal))print("123 is int = " , isinstance(123,int))print("'123' is str = " , isinstance('123',str))print("b'a' is bytes = " , isinstance(b'a',bytes))print("[1,2,3] is list or tuple",isinstance([1,2,3],(list,tuple))) # 判断一个变量是否是某些类型中的其中一种
输出结果:
dog is Animal = True
123 is int = True
‘123’ is str = True
b’a’ is bytes = True
[1,2,3] is list or tuple True
dir() 获取对象所有属性和方法
print(dir("abc"))print(dir(123))
输出结果:
[‘add‘, ‘class‘, ‘contains‘, ‘delattr‘, ‘dir‘, ‘doc‘, ‘eq‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘getitem‘, ‘getnewargs‘, ‘gt‘, ‘hash‘, ‘init‘, ‘init_subclass‘, ‘iter‘, ‘le‘, ‘len‘, ‘lt‘, ‘mod‘, ‘mul‘, ‘ne‘, ‘new‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘rmod‘, ‘rmul‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘subclasshook‘, ‘capitalize’, ‘casefold’, ‘center’, ‘count’, ‘encode’, ‘endswith’, ‘expandtabs’, ‘find’, ‘format’, ‘format_map’, ‘index’, ‘isalnum’, ‘isalpha’, ‘isdecimal’, ‘isdigit’, ‘isidentifier’, ‘islower’, ‘isnumeric’, ‘isprintable’, ‘isspace’, ‘istitle’, ‘isupper’, ‘join’, ‘ljust’, ‘lower’, ‘lstrip’, ‘maketrans’, ‘partition’, ‘replace’, ‘rfind’, ‘rindex’, ‘rjust’, ‘rpartition’, ‘rsplit’, ‘rstrip’, ‘split’, ‘splitlines’, ‘startswith’, ‘strip’, ‘swapcase’, ‘title’, ‘translate’, ‘upper’, ‘zfill’]
[‘abs‘, ‘add‘, ‘and‘, ‘bool‘, ‘ceil‘, ‘class‘, ‘delattr‘, ‘dir‘, ‘divmod‘, ‘doc‘, ‘eq‘, ‘float‘, ‘floor‘, ‘floordiv‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘getnewargs‘, ‘gt‘, ‘hash‘, ‘index‘, ‘init‘, ‘init_subclass‘, ‘int‘, ‘invert‘, ‘le‘, ‘lshift‘, ‘lt‘, ‘mod‘, ‘mul‘, ‘ne‘, ‘neg‘, ‘new‘, ‘or‘, ‘pos‘, ‘pow‘, ‘radd‘, ‘rand‘, ‘rdivmod‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘rfloordiv‘, ‘rlshift‘, ‘rmod‘, ‘rmul‘, ‘ror‘, ‘round‘, ‘rpow‘, ‘rrshift‘, ‘rshift‘, ‘rsub‘, ‘rtruediv‘, ‘rxor‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘sub‘, ‘subclasshook‘, ‘truediv‘, ‘trunc‘, ‘xor‘, ‘bit_length’, ‘conjugate’, ‘denominator’, ‘from_bytes’, ‘imag’, ‘numerator’, ‘real’, ‘to_bytes’]
注意:类似 XXX的属性和方法在 Python 中都是特殊用途的,比如 len方法返回长度,当调用 len() 函数获取对象的长度,实际上,在 len() 函数内部,他自动调用该对象的 len() 方法。
所以,以下写法是等价的:
print(len("123456"))print("123456".__len__())
我们自定义的类,想要使用 len(myObj),就需要自己写一个 len() 方法,因为, len() 方法内部调用的是 len() 方法。
class Rectangle(object) : def __init__(self,length,width): self.length = length self.width = width def __len__(self): return 2*(self.length + self.width)rect = Rectangle(10,7)print(len(rect))
如果没有定义 len() 方法,那么输出报错:
Traceback (most recent call last): File "E:/Python/HelloWorld.py", line 248, in <module> print(len(rect))TypeError: object of type 'Rectangle' has no len()
另外,Python 提供了操作属性的方法:
- getattr() : 获取属性
- setattr() : 设置属性
- hasattr() : 判断是否存在属性
class Rectangle(object) :def __init__(self,length,width): self.length = length self.width = widthdef __len__(self): return 2*(self.length + self.width)rect = Rectangle(10,7)print("has attr length = ",hasattr(rect,"length"))print("has attr area = ",hasattr(rect,"area"))setattr(rect,"centerX",10)print("has attr centerX = ",hasattr(rect,"centerX"))print("get attr centerX = ",getattr(rect,"centerX"))
输出结果:
has attr length = True
has attr area = False
has attr centerX = True
get attr centerX = 10
实例属性和类属性
实例属性只属于某个实例,每个实例的属性的值可能不相同。
类属性是属于某个类的,所有实例共享同一个属性。
class Teacher(object): job_occupation = "teacher" def __init__(self, name): self.name = name def print(self): print("name = ", self.name, "job = ",self.job_occupation)jane_teacher = Teacher("jane")tom_teacher = Teacher("tom")jane_teacher.print()tom_teacher.print()print(Teacher.job_occupation)
上面示例中, job_occupation 即是类属性,
输出结果:
name = jane job = teacher
name = tom job = teacher
teacher
注意:当实例属性和类属性使用相同的名字时,实例属性将屏蔽掉类属性。
实例动态绑定属性和方法
当创建了类的实例后,我们可以给该实例绑定任何属性和方法。
class Student(object): passstu = Student()print("stu has attr name = ",hasattr(stu,"name")) # False# 实例对象绑定属性stu.name = "tomcat"print("stu has attr name = ",hasattr(stu,"name")) # Trueif hasattr(stu,"name"): print("name = ",stu.name)# 实例对象绑定方法def set_stu_name(self,name): self.name = namefrom types import MethodTypestu.set_stu_name = MethodType(set_stu_name,stu)stu.set_stu_name("luck")print(stu.name)# 给所有实例绑定方法,即给 class 类绑定方法def set_score(self,score): self.score = scoreStudent.set_score = set_scorestu2 = Student()stu2.set_score(90)print(stu2.score)
输出结果:
stu has attr name = False
stu has attr name = True
name = tomcat
luck
90
多重继承
Python 允许使用多重继承,即一个类继承多个类。
class Runnable(object): def run(self): print("run....")class Sleepable(object): def sleep(self): print("slepp...")class LiveAnimal(Runnable,Sleepable) : def printAbility(self): self.run() self.sleep()liveAnimal = LiveAnimal()liveAnimal.printAbility()
输出结果:
run….
slepp…
定制对象的输出形式 : _ str _
和 Java 相似,默认情况下,直接打印出对象时,输出的是对象的内存地址,我们可以重写 _ str _ 方法来定制输出结果。
class Person(object): def __init__(self,name,age): self.name = name self.age = ageperson = Person("mike",22)print(person)
没有重写 _ str _ 方法,输出结果:
<main.Person object at 0x01D8C4B0>
下面我们重写了 Person 的 _ str_ 方法,定制出我们想要的输出结果。
class Person(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return "name = %s , age = %s" % (self.name, self.age)person = Person("mike", 22)print(person)
输出结果:
name = mike , age = 22
Python 面向对象
在 Python 中,所有的数据类型都可以视为对象,当然也可以自定义对象,自定义对象数据类型就是面向对象中的类 Class 的概念。
- 类:用来描述具有相同属性和方法的对象的集合,它定义了该集合中每个对象的共有的属性和方法。
- 类变量:类变量在整个实例化的对象中是公有的,类变量定义在类中且在函数体外。
- 实例变量:定义在方法中的变量,只能作用于当前实例。
- 实例化:即创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。
创建类
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾。
class ClassName: '类的帮助信息' #类文档信息 类变量 方法 数据属性
例子:
class Employee(object): 'Employee 雇员类' empCount = 1 # 类变量 def __init__(self, name, age): self.__name = name # 实例变量 self.__age = age # 实例变量 def printCount(self): print("Total employee = %d" % Employee.empCount) def printEmployee(self): print("name = %s ,age = %d" % (self.__name, self.__age))
- 类名后面的 (object) 表示这个类是从哪个类继承下来的, object 是所有类的父类。
- _ init_() 方法是是类的构造函数或初始化方法,当创建类的实例时就会调用这个方法。
- self 代表类的实例,self 参数在定义类的方法时必须有的,在创建实例时,self 参数不需要传入,解释器自己会把实例变量传进去。
- 实例变量在变量名前面加上两个下划线就变成了一个私有变量,只有类内部可以访问,外部不能访问;这样确保外部代码不能随意修改对象内部的属性的值。双下划线的变量不能再类外直接访问,是因为解释器对外把 __name 变量改成了 _Person__name ,所以,任然可以通过 _Student__name 来访问 __name 变量。
- 同时,可以给类定义get ,set 方法,用于获取和修改类的属性。
创建实例对象
创建实例使用 类名(参数…),其中参数对应于定义类时的 init 方法中的参数。
e = Employee("tomcat",22)e.printCount()e.printEmployee()
输出结果:
Total employee = 1
name = tomcat ,age = 22
Python 内置类属性
- _ dict _:类的属性,由类的数据属性组成
- _ doc _:类的文档字符串
- _ name _:类名
- _ module _:类定义所在的模块
- _ bases _:类的所有父类构成元素
print("Employee.__doc__:",Employee.__doc__)print("Employee.__name__:",Employee.__name__)print("Employee.__module__:",Employee.__module__ )print("Employee.__bases__:",Employee.__bases__)print("Employee.__dict__:",Employee.__dict__)
输出结果:
Employee.doc: Employee 雇员类
Employee.name: Employee
Employee.module: main
Employee.bases: (
继承
语法: class 派生类名(基类名):
基类:
class Animal(object): def run(self): print("Animal run.....")
子类:
class Dog(Animal): passclass Cat(Animal): passdog = Dog()cat = Cat()dog.run()cat.run()
输出结果:
Animal run…..
Animal run…..
子类自动继承了父类中方法。
注意:
1. 在继承中基类的构造(init() 方法) 不会被自动调用,需要在其派生类的构造中亲自专门调用。
2. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量,区别在于类中调用普通函数时,并不需要带上 self 参数。
3. Python 总是首先查找对应类型的方法,如果他不能再派生类中找到对应的方法,他才开始到基类中逐个查找。
方法覆盖
class Dog(Animal): def run(self): print("Dog run....")class Cat(Animal): def run(self): print("Cat run....")dog = Dog()cat = Cat()dog.run()cat.run()
输出结果:
Dog run….
Cat run….
当子类和父类都存在相同的方法时,子类方法覆盖了父类的方法,在代码执行时,调用的是子类中的那个方法。
多态
def run_animal(animal): animal.run()run_animal(dog)run_animal(cat)
输出结果:
Dog run….
Cat run….
可见,Animal类型的参数,可以传入 Dog,Cat 类型变量,只有传入的参数类型是 Animal 的子类,都可以接收。
鸭子模型
对于静态语言(Java)来说,如果需要传入 Animal 类型,则传入的对象必须是 Animal 类型或者他的子类,否则,将无法调用 run() 方法。但是,对用 Python 这种动态语言来说,则不一定需要传入 Animal 类型,只需保证传入的对象有一个 run() 方法即可。
type() 获取对象信息
使用 type() 函数可以判断出对象的类型。
print(type(123))print(type("123"))print(type(None))print(type([1,2,3]))print(type((1,2,3)))print(type({"Android":"Google","iOS":"Apple"}))print(type(True))print(type(abs)) # abs 绝对值,内置函数print(type(dog))
输出结果:
判断对象是否是函数
import typesdef function_add(): passfunction_res = type(function_add) == types.FunctionTypeprint(function_res)
输出结果: True
对象是否是类的实例 - isinstance()
print("dog is Animal = " , isinstance(dog,Animal))print("123 is int = " , isinstance(123,int))print("'123' is str = " , isinstance('123',str))print("b'a' is bytes = " , isinstance(b'a',bytes))print("[1,2,3] is list or tuple",isinstance([1,2,3],(list,tuple))) # 判断一个变量是否是某些类型中的其中一种
输出结果:
dog is Animal = True
123 is int = True
‘123’ is str = True
b’a’ is bytes = True
[1,2,3] is list or tuple True
dir() 获取对象所有属性和方法
print(dir("abc"))print(dir(123))
输出结果:
[‘add‘, ‘class‘, ‘contains‘, ‘delattr‘, ‘dir‘, ‘doc‘, ‘eq‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘getitem‘, ‘getnewargs‘, ‘gt‘, ‘hash‘, ‘init‘, ‘init_subclass‘, ‘iter‘, ‘le‘, ‘len‘, ‘lt‘, ‘mod‘, ‘mul‘, ‘ne‘, ‘new‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘rmod‘, ‘rmul‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘subclasshook‘, ‘capitalize’, ‘casefold’, ‘center’, ‘count’, ‘encode’, ‘endswith’, ‘expandtabs’, ‘find’, ‘format’, ‘format_map’, ‘index’, ‘isalnum’, ‘isalpha’, ‘isdecimal’, ‘isdigit’, ‘isidentifier’, ‘islower’, ‘isnumeric’, ‘isprintable’, ‘isspace’, ‘istitle’, ‘isupper’, ‘join’, ‘ljust’, ‘lower’, ‘lstrip’, ‘maketrans’, ‘partition’, ‘replace’, ‘rfind’, ‘rindex’, ‘rjust’, ‘rpartition’, ‘rsplit’, ‘rstrip’, ‘split’, ‘splitlines’, ‘startswith’, ‘strip’, ‘swapcase’, ‘title’, ‘translate’, ‘upper’, ‘zfill’]
[‘abs‘, ‘add‘, ‘and‘, ‘bool‘, ‘ceil‘, ‘class‘, ‘delattr‘, ‘dir‘, ‘divmod‘, ‘doc‘, ‘eq‘, ‘float‘, ‘floor‘, ‘floordiv‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘getnewargs‘, ‘gt‘, ‘hash‘, ‘index‘, ‘init‘, ‘init_subclass‘, ‘int‘, ‘invert‘, ‘le‘, ‘lshift‘, ‘lt‘, ‘mod‘, ‘mul‘, ‘ne‘, ‘neg‘, ‘new‘, ‘or‘, ‘pos‘, ‘pow‘, ‘radd‘, ‘rand‘, ‘rdivmod‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘rfloordiv‘, ‘rlshift‘, ‘rmod‘, ‘rmul‘, ‘ror‘, ‘round‘, ‘rpow‘, ‘rrshift‘, ‘rshift‘, ‘rsub‘, ‘rtruediv‘, ‘rxor‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘sub‘, ‘subclasshook‘, ‘truediv‘, ‘trunc‘, ‘xor‘, ‘bit_length’, ‘conjugate’, ‘denominator’, ‘from_bytes’, ‘imag’, ‘numerator’, ‘real’, ‘to_bytes’]
注意:类似 XXX的属性和方法在 Python 中都是特殊用途的,比如 len方法返回长度,当调用 len() 函数获取对象的长度,实际上,在 len() 函数内部,他自动调用该对象的 len() 方法。
所以,以下写法是等价的:
print(len("123456"))print("123456".__len__())
我们自定义的类,想要使用 len(myObj),就需要自己写一个 len() 方法,因为, len() 方法内部调用的是 len() 方法。
class Rectangle(object) : def __init__(self,length,width): self.length = length self.width = width def __len__(self): return 2*(self.length + self.width)rect = Rectangle(10,7)print(len(rect))
如果没有定义 len() 方法,那么输出报错:
Traceback (most recent call last): File "E:/Python/HelloWorld.py", line 248, in <module> print(len(rect))TypeError: object of type 'Rectangle' has no len()
另外,Python 提供了操作属性的方法:
- getattr() : 获取属性
- setattr() : 设置属性
- hasattr() : 判断是否存在属性
class Rectangle(object) :def __init__(self,length,width): self.length = length self.width = widthdef __len__(self): return 2*(self.length + self.width)rect = Rectangle(10,7)print("has attr length = ",hasattr(rect,"length"))print("has attr area = ",hasattr(rect,"area"))setattr(rect,"centerX",10)print("has attr centerX = ",hasattr(rect,"centerX"))print("get attr centerX = ",getattr(rect,"centerX"))
输出结果:
has attr length = True
has attr area = False
has attr centerX = True
get attr centerX = 10
实例属性和类属性
实例属性只属于某个实例,每个实例的属性的值可能不相同。
类属性是属于某个类的,所有实例共享同一个属性。
class Teacher(object): job_occupation = "teacher" def __init__(self, name): self.name = name def print(self): print("name = ", self.name, "job = ",self.job_occupation)jane_teacher = Teacher("jane")tom_teacher = Teacher("tom")jane_teacher.print()tom_teacher.print()print(Teacher.job_occupation)
上面示例中, job_occupation 即是类属性,
输出结果:
name = jane job = teacher
name = tom job = teacher
teacher
注意:当实例属性和类属性使用相同的名字时,实例属性将屏蔽掉类属性。
实例动态绑定属性和方法
当创建了类的实例后,我们可以给该实例绑定任何属性和方法。
class Student(object): passstu = Student()print("stu has attr name = ",hasattr(stu,"name")) # False# 实例对象绑定属性stu.name = "tomcat"print("stu has attr name = ",hasattr(stu,"name")) # Trueif hasattr(stu,"name"): print("name = ",stu.name)# 实例对象绑定方法def set_stu_name(self,name): self.name = namefrom types import MethodTypestu.set_stu_name = MethodType(set_stu_name,stu)stu.set_stu_name("luck")print(stu.name)# 给所有实例绑定方法,即给 class 类绑定方法def set_score(self,score): self.score = scoreStudent.set_score = set_scorestu2 = Student()stu2.set_score(90)print(stu2.score)
输出结果:
stu has attr name = False
stu has attr name = True
name = tomcat
luck
90
多重继承
Python 允许使用多重继承,即一个类继承多个类。
class Runnable(object): def run(self): print("run....")class Sleepable(object): def sleep(self): print("slepp...")class LiveAnimal(Runnable,Sleepable) : def printAbility(self): self.run() self.sleep()liveAnimal = LiveAnimal()liveAnimal.printAbility()
输出结果:
run….
slepp…
定制对象的输出形式 : _ str _
和 Java 相似,默认情况下,直接打印出对象时,输出的是对象的内存地址,我们可以重写 _ str _ 方法来定制输出结果。
class Person(object): def __init__(self,name,age): self.name = name self.age = ageperson = Person("mike",22)print(person)
没有重写 _ str _ 方法,输出结果:
<main.Person object at 0x01D8C4B0>
下面我们重写了 Person 的 _ str_ 方法,定制出我们想要的输出结果。
class Person(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return "name = %s , age = %s" % (self.name, self.age)person = Person("mike", 22)print(person)
输出结果:
name = mike , age = 22
Python 面向对象
在 Python 中,所有的数据类型都可以视为对象,当然也可以自定义对象,自定义对象数据类型就是面向对象中的类 Class 的概念。
- 类:用来描述具有相同属性和方法的对象的集合,它定义了该集合中每个对象的共有的属性和方法。
- 类变量:类变量在整个实例化的对象中是公有的,类变量定义在类中且在函数体外。
- 实例变量:定义在方法中的变量,只能作用于当前实例。
- 实例化:即创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。
创建类
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾。
class ClassName: '类的帮助信息' #类文档信息 类变量 方法 数据属性
例子:
class Employee(object): 'Employee 雇员类' empCount = 1 # 类变量 def __init__(self, name, age): self.__name = name # 实例变量 self.__age = age # 实例变量 def printCount(self): print("Total employee = %d" % Employee.empCount) def printEmployee(self): print("name = %s ,age = %d" % (self.__name, self.__age))
- 类名后面的 (object) 表示这个类是从哪个类继承下来的, object 是所有类的父类。
- _ init_() 方法是是类的构造函数或初始化方法,当创建类的实例时就会调用这个方法。
- self 代表类的实例,self 参数在定义类的方法时必须有的,在创建实例时,self 参数不需要传入,解释器自己会把实例变量传进去。
- 实例变量在变量名前面加上两个下划线就变成了一个私有变量,只有类内部可以访问,外部不能访问;这样确保外部代码不能随意修改对象内部的属性的值。双下划线的变量不能再类外直接访问,是因为解释器对外把 __name 变量改成了 _Person__name ,所以,任然可以通过 _Student__name 来访问 __name 变量。
- 同时,可以给类定义get ,set 方法,用于获取和修改类的属性。
创建实例对象
创建实例使用 类名(参数…),其中参数对应于定义类时的 init 方法中的参数。
e = Employee("tomcat",22)e.printCount()e.printEmployee()
输出结果:
Total employee = 1
name = tomcat ,age = 22
Python 内置类属性
- _ dict _:类的属性,由类的数据属性组成
- _ doc _:类的文档字符串
- _ name _:类名
- _ module _:类定义所在的模块
- _ bases _:类的所有父类构成元素
print("Employee.__doc__:",Employee.__doc__)print("Employee.__name__:",Employee.__name__)print("Employee.__module__:",Employee.__module__ )print("Employee.__bases__:",Employee.__bases__)print("Employee.__dict__:",Employee.__dict__)
输出结果:
Employee.doc: Employee 雇员类
Employee.name: Employee
Employee.module: main
Employee.bases: (
继承
语法: class 派生类名(基类名):
基类:
class Animal(object): def run(self): print("Animal run.....")
子类:
class Dog(Animal): passclass Cat(Animal): passdog = Dog()cat = Cat()dog.run()cat.run()
输出结果:
Animal run…..
Animal run…..
子类自动继承了父类中方法。
注意:
1. 在继承中基类的构造(init() 方法) 不会被自动调用,需要在其派生类的构造中亲自专门调用。
2. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量,区别在于类中调用普通函数时,并不需要带上 self 参数。
3. Python 总是首先查找对应类型的方法,如果他不能再派生类中找到对应的方法,他才开始到基类中逐个查找。
方法覆盖
class Dog(Animal): def run(self): print("Dog run....")class Cat(Animal): def run(self): print("Cat run....")dog = Dog()cat = Cat()dog.run()cat.run()
输出结果:
Dog run….
Cat run….
当子类和父类都存在相同的方法时,子类方法覆盖了父类的方法,在代码执行时,调用的是子类中的那个方法。
多态
def run_animal(animal): animal.run()run_animal(dog)run_animal(cat)
输出结果:
Dog run….
Cat run….
可见,Animal类型的参数,可以传入 Dog,Cat 类型变量,只有传入的参数类型是 Animal 的子类,都可以接收。
鸭子模型
对于静态语言(Java)来说,如果需要传入 Animal 类型,则传入的对象必须是 Animal 类型或者他的子类,否则,将无法调用 run() 方法。但是,对用 Python 这种动态语言来说,则不一定需要传入 Animal 类型,只需保证传入的对象有一个 run() 方法即可。
type() 获取对象信息
使用 type() 函数可以判断出对象的类型。
print(type(123))print(type("123"))print(type(None))print(type([1,2,3]))print(type((1,2,3)))print(type({"Android":"Google","iOS":"Apple"}))print(type(True))print(type(abs)) # abs 绝对值,内置函数print(type(dog))
输出结果:
判断对象是否是函数
import typesdef function_add(): passfunction_res = type(function_add) == types.FunctionTypeprint(function_res)
输出结果: True
对象是否是类的实例 - isinstance()
print("dog is Animal = " , isinstance(dog,Animal))print("123 is int = " , isinstance(123,int))print("'123' is str = " , isinstance('123',str))print("b'a' is bytes = " , isinstance(b'a',bytes))print("[1,2,3] is list or tuple",isinstance([1,2,3],(list,tuple))) # 判断一个变量是否是某些类型中的其中一种
输出结果:
dog is Animal = True
123 is int = True
‘123’ is str = True
b’a’ is bytes = True
[1,2,3] is list or tuple True
dir() 获取对象所有属性和方法
print(dir("abc"))print(dir(123))
输出结果:
[‘add‘, ‘class‘, ‘contains‘, ‘delattr‘, ‘dir‘, ‘doc‘, ‘eq‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘getitem‘, ‘getnewargs‘, ‘gt‘, ‘hash‘, ‘init‘, ‘init_subclass‘, ‘iter‘, ‘le‘, ‘len‘, ‘lt‘, ‘mod‘, ‘mul‘, ‘ne‘, ‘new‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘rmod‘, ‘rmul‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘subclasshook‘, ‘capitalize’, ‘casefold’, ‘center’, ‘count’, ‘encode’, ‘endswith’, ‘expandtabs’, ‘find’, ‘format’, ‘format_map’, ‘index’, ‘isalnum’, ‘isalpha’, ‘isdecimal’, ‘isdigit’, ‘isidentifier’, ‘islower’, ‘isnumeric’, ‘isprintable’, ‘isspace’, ‘istitle’, ‘isupper’, ‘join’, ‘ljust’, ‘lower’, ‘lstrip’, ‘maketrans’, ‘partition’, ‘replace’, ‘rfind’, ‘rindex’, ‘rjust’, ‘rpartition’, ‘rsplit’, ‘rstrip’, ‘split’, ‘splitlines’, ‘startswith’, ‘strip’, ‘swapcase’, ‘title’, ‘translate’, ‘upper’, ‘zfill’]
[‘abs‘, ‘add‘, ‘and‘, ‘bool‘, ‘ceil‘, ‘class‘, ‘delattr‘, ‘dir‘, ‘divmod‘, ‘doc‘, ‘eq‘, ‘float‘, ‘floor‘, ‘floordiv‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘getnewargs‘, ‘gt‘, ‘hash‘, ‘index‘, ‘init‘, ‘init_subclass‘, ‘int‘, ‘invert‘, ‘le‘, ‘lshift‘, ‘lt‘, ‘mod‘, ‘mul‘, ‘ne‘, ‘neg‘, ‘new‘, ‘or‘, ‘pos‘, ‘pow‘, ‘radd‘, ‘rand‘, ‘rdivmod‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘rfloordiv‘, ‘rlshift‘, ‘rmod‘, ‘rmul‘, ‘ror‘, ‘round‘, ‘rpow‘, ‘rrshift‘, ‘rshift‘, ‘rsub‘, ‘rtruediv‘, ‘rxor‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘sub‘, ‘subclasshook‘, ‘truediv‘, ‘trunc‘, ‘xor‘, ‘bit_length’, ‘conjugate’, ‘denominator’, ‘from_bytes’, ‘imag’, ‘numerator’, ‘real’, ‘to_bytes’]
注意:类似 XXX的属性和方法在 Python 中都是特殊用途的,比如 len方法返回长度,当调用 len() 函数获取对象的长度,实际上,在 len() 函数内部,他自动调用该对象的 len() 方法。
所以,以下写法是等价的:
print(len("123456"))print("123456".__len__())
我们自定义的类,想要使用 len(myObj),就需要自己写一个 len() 方法,因为, len() 方法内部调用的是 len() 方法。
class Rectangle(object) : def __init__(self,length,width): self.length = length self.width = width def __len__(self): return 2*(self.length + self.width)rect = Rectangle(10,7)print(len(rect))
如果没有定义 len() 方法,那么输出报错:
Traceback (most recent call last): File "E:/Python/HelloWorld.py", line 248, in <module> print(len(rect))TypeError: object of type 'Rectangle' has no len()
另外,Python 提供了操作属性的方法:
- getattr() : 获取属性
- setattr() : 设置属性
- hasattr() : 判断是否存在属性
class Rectangle(object) :def __init__(self,length,width): self.length = length self.width = widthdef __len__(self): return 2*(self.length + self.width)rect = Rectangle(10,7)print("has attr length = ",hasattr(rect,"length"))print("has attr area = ",hasattr(rect,"area"))setattr(rect,"centerX",10)print("has attr centerX = ",hasattr(rect,"centerX"))print("get attr centerX = ",getattr(rect,"centerX"))
输出结果:
has attr length = True
has attr area = False
has attr centerX = True
get attr centerX = 10
实例属性和类属性
实例属性只属于某个实例,每个实例的属性的值可能不相同。
类属性是属于某个类的,所有实例共享同一个属性。
class Teacher(object): job_occupation = "teacher" def __init__(self, name): self.name = name def print(self): print("name = ", self.name, "job = ",self.job_occupation)jane_teacher = Teacher("jane")tom_teacher = Teacher("tom")jane_teacher.print()tom_teacher.print()print(Teacher.job_occupation)
上面示例中, job_occupation 即是类属性,
输出结果:
name = jane job = teacher
name = tom job = teacher
teacher
注意:当实例属性和类属性使用相同的名字时,实例属性将屏蔽掉类属性。
实例动态绑定属性和方法
当创建了类的实例后,我们可以给该实例绑定任何属性和方法。
class Student(object): passstu = Student()print("stu has attr name = ",hasattr(stu,"name")) # False# 实例对象绑定属性stu.name = "tomcat"print("stu has attr name = ",hasattr(stu,"name")) # Trueif hasattr(stu,"name"): print("name = ",stu.name)# 实例对象绑定方法def set_stu_name(self,name): self.name = namefrom types import MethodTypestu.set_stu_name = MethodType(set_stu_name,stu)stu.set_stu_name("luck")print(stu.name)# 给所有实例绑定方法,即给 class 类绑定方法def set_score(self,score): self.score = scoreStudent.set_score = set_scorestu2 = Student()stu2.set_score(90)print(stu2.score)
输出结果:
stu has attr name = False
stu has attr name = True
name = tomcat
luck
90
多重继承
Python 允许使用多重继承,即一个类继承多个类。
class Runnable(object): def run(self): print("run....")class Sleepable(object): def sleep(self): print("slepp...")class LiveAnimal(Runnable,Sleepable) : def printAbility(self): self.run() self.sleep()liveAnimal = LiveAnimal()liveAnimal.printAbility()
输出结果:
run….
slepp…
定制对象的输出形式 : _ str _
和 Java 相似,默认情况下,直接打印出对象时,输出的是对象的内存地址,我们可以重写 _ str _ 方法来定制输出结果。
class Person(object): def __init__(self,name,age): self.name = name self.age = ageperson = Person("mike",22)print(person)
没有重写 _ str _ 方法,输出结果:
<main.Person object at 0x01D8C4B0>
下面我们重写了 Person 的 _ str_ 方法,定制出我们想要的输出结果。
class Person(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return "name = %s , age = %s" % (self.name, self.age)person = Person("mike", 22)print(person)
输出结果:
name = mike , age = 22
- Python 深入浅出
- Python 深入浅出
- Python 深入浅出
- Python 深入浅出
- Python 深入浅出
- 深入浅出python 1
- 深入浅出Python装饰器
- 深入浅出Python装饰器
- 深入浅出python闭包
- 深入浅出 Python Iterators 迭代器
- 深入浅出 Python Generators
- 深入浅出 Python Closures
- 深入浅出 Python Decorators
- 深入浅出 Python Descriptors / Properties
- 深入浅出Python(中文版) 下载地址
- 深入浅出理解python 装饰器
- python yield函数深入浅出理解
- 深入浅出Python中的异步编程
- Deep Forest:一种深度神经网络的替代模型架构
- Arrays.binarySearch()返回值问题
- python中的“self”
- vue阻止事件冒泡
- JAVA中的Pattern
- Python 深入浅出
- VS2017常见问题解决
- 如何做出漂亮的序列比对图——ENDscript/ESPript
- getopt和getopt_long
- gwo灰狼算法matlab源码
- 计算机语言之战
- vuejs进阶之路一基础知识 2017-12-16
- git Authentication failed解决办法
- Python Json树更新