定义类和属性:
# 多个单词组成的类使用驼峰式命名。
# class 类默认继承 object 类。
class Phone :
# 属性
brand = ""
# 方法
a = Phone()
print(a)
# <__main__.Phone object at 0x00000275B251F148>
# 创建一个对象并赋值给a,a为在地址为 0x00000275B251F148 的空间上的对象。
print(a.brand)
# 132213
a.brand = "aaaaaaa"
print(a.brand)
# aaaaaaa
# 创建对象时,如果不提另赋值,属性会使用定义类时的默认值。
如果需要添加专有的属性,需要另外定义。
面向对象的方法:
种类:普通方法,类方法,静态方法,魔术方法。
传递的参数可以是各种类型的变量或某个类的对象。
__ init __: 初始化,相当于构造函数,创建对象时的参数被传到这个函数的参数中,创建函数需要的参数要和init的参数相同。
类方法:
特点:
1.定义需要依赖装饰器@classmethod。
2.类方法中参数不是一个对象,而是类。
3.类方法中只能使用类属性。
4.类方法中不能使用普通方法,因为普通方法需要调用对象。而类方法是创建类的时候加载进内存的,没有对象可调用。普通方法可以调用类方法。
作用:
因为只能访问类属性和类方法,可以在对象创建之前完成一些操作。
class Dog:
@classmethod
def test(cls):
#cls,在这里是class的简写。
print('--------->')
print(cls)
def __init__(self,nickname):
self.nickname = nickname
def run(self):
print("running!")
self.test()
d = Dog("www")
d.test()
# <class '__main__.Dog'>
Dog.test()
# <class '__main__.Dog'>
d.run()
# running!
# --------->
# <class '__main__.Dog'>
静态方法:
1.需要 staticmethod 作为装饰器。
2.无需传递参数。
3.只能访问类的属性和方法,对象的无法访问。
4.类创建的时候静态方法就已经出现了。
5.与类方法的区别是装饰器和没有 cls 参数。共同点是在对象创建之前就能使用。
class Dog:
age = 1
@staticmethod
def test():
#cls,在这里是class的简写。
Dog.age += 1
print(Dog.age)
def __init__(self,nickname):
self.nickname = nickname
def run(self):
self.age += 1000
print(Dog.age)
d = Dog("aaaaaa")
d.run()
# 1
Dog.test()
# 2
Dog.test()
# 3
Dog.test()
# 4
魔术方法:
__ init __:构造函数,初始化对象时触发。
__ new __ :实例的魔术方法,在实例化时进行触发。
p = person("aaaa")
在这个过程中会调用new和init。向内存申请地址,再调用init对地址进行操作,最后将这个初始化之后的对象返回给p。
__ call __:把对象当成函数调用时默认调用这个函数里的东西。但是如果想调用的话,一定要重新定义call函数。
__ del __: 析构函数,python解释器会回收在一次执行过程中的所有变量。
class Person(object):
name = ""
def __init__(self,name):
self.name = name
print("initname of p = {}".format(self.name))
def Changename(self,newname):
self.name = newname
def __del__(self):
print("del")
p = Person("Jack")
# initname of p = Jack
p1 = p
print("oldname of p1 = ",p1.name)
# oldname of p1 = Jack
p.Changename("Tom")
p1 = p
print("newname of p2 = ",p1.name)
# newname of p2 = Tom
del p1
print(p1.name)
print(p.name)
# NameError: name 'p1' is not defined
__ str __: 打印对象名的时候触发。
class Person(object):
name = ""
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return self.name+str(self.age)
p = Person("adadad",12)
print(p)
# adadad12
str一定要有返回值,并且返回值类型为字符串类型,可以是format的形式,多个字符串要以相加的形式返回,否则会报出TypeError。
私有化:
封装:
1.私有化属性
2.定义共有set和get方法访问私有化属性。
好处:
1.隐藏属性不被外界修改,只有get和set可以修改。
2.可以将更改的内容进行修改,可以在set里进行限制。
以 __名称 来命名私有化,在运行的时候会被转换成其他的名称。比如说class student中的 __name 属性,在python运行过程中会被转换成 _student__age,这里的私有只是让调用它的函数或对象找不到而已。
property装饰方式:
class Person(object):
def __init__(self,name,age):
self.name = name
self.__age = age
@property
def getage(self):
return self.__age
@getage.setter
def setage(self,age):
if age > 0 and age < 100:
self.__age = age
else:
print("输入的age不合法!")
print(type(Person.getage))
# <class 'property'>
print(type(Person.setage))
# <class 'property'>
p = Person("adadad",12)
p.setage = 1000
# 输入的age不合法!
print(p.getage)
# 12
这里getage函数运用了装饰器property,可以看出,getage加了装饰器之后变成了property对象。**property可以get和set,set必须在get之后。**通过调用使用property类对象名.setter装饰的函数,可以起到set的作用。
使用时可将get函数和set函数作为一个变量使用。具体使用方法见代码中。
**注意:**这里的get和set不是系统默认的名称,可以自行命名,我只是将他们按照功能命名。
has a 和 is a:
has a 表示的是一个类中包含其他类的对象
is a 表示的是继承的关系,一个类是另一个的子类
class Computer:
def __init__(self,brand,type,color):
self.brand = brand
self.type = type
self.color = color
def online(self):
print("正在使用电脑上网......")
def __str__(self):
return self.color+"--"+self.brand + "--" + self.type
class Book:
def __init__(self,bname,author,number):
self.bname = bname
self.author = author
self.number = number
def __str__(self):
return self.bname + "--" + self.author + "--" + str(self.number)
class Student:
def __init__(self,name,computer,book):
self.name = name
self.computer = computer
self.books = []
self.books.append(book)
def __str__(self):
return self.name + "--" + str(self.computer) + "--" + str(self.books)
def borrow_book(self,book,):
pass
computer = Computer("mac","mac pro 2018","深灰色")
book = Book("盗墓笔记","南派三叔", 10)
stu = Student("sname",computer,book)
print(stu)
# sname--深灰色--mac--mac pro 2018--[<__main__.Book object at 0x000001FB1DC199C8>]
这里的student 包含了book 和 computer 类的对象,属于has a的关系。
对于代码需要说明的一点是:
def __str__(self):
return self.name + "--" + str(self.computer) + "--" + str(self.books)
return后面,student 类中 __ str __ 的返回值包含 computer 类对象时,不会将 computer 对象用computer的__ str __函数转换成 str 类型,而是直接报错。
继承:
为了避免代码冗余,可读性不高,引入了继承的机制。
定义方法:class 子类(父类):
class Person:
def __init__(self,name,age):
self.name = "None"
self.age = 18
def eat(self):
print(self.name + "eating")
def run(self):
print(self.name + "running")
class Student(Person):
def __init__(self,name,age):
print("----->student中的init")
super().__init__(name,age)
class Employee(Person):
def __init__(self,name,age,salary,manager):
super().__init__(name,age)
self.salary = salary
self.manager = manager
class Doctor(Person):
def __init__(self,name,age,patients):
super().__init__(name,age)
self.patients = patients
每个子类都有自己的特点,所以要用自己的init,也有各自的共同点,所以调用父类
的init函数,从而使代码更加简洁。
特点:
1.如果不定义init,调用父类的super class的init
2.如果要定义自己的init,就要在自己的init里加入父类的init,方法:super().__init __。
super(类名,对象).__init __。
3.父类和子类中有相同的方法,先从当前类中找,没有的话去父类中找,把这个行为称为重写(覆盖),需要调用父类中的方法,可以用super(),方法名。
多继承:
python支持多继承,并能直接访问父类的函数。
调用函数时搜索顺序是广度优先:python3中先自身。然后再从继承的类中按照自身声明的次序搜索。深度优先:python2中先搜索第一个父类,再搜索这个父类的父类,知道没有父类为止。
这种有规律的搜索避免了多继承时各个父类出现同名函数而导致的情况。
多态:
python中无严格的多态。
当一个参数为父类时,传递给那个参数子类的对象是可以使用的。
class Person(object):
def feed(self,pet):
if isinstance(pet,Pet):
print("feeding {}...".format(pet.name))
else:
print("Not pet!")
class Pet(object):
def __init__(self,name):
self.name = name
class Cat(Pet):
def __init__(self,name,type):
super().__init__(name)
self.type = type
p = Person()
cat = Cat("m","cat")
pet1 = Pet("ttt")
p.feed(cat)
# feeding m...
p.feed(pet1)
# feeding ttt...
cat是cat类,pet1是pet类,cat类是pet类的子类,再调用person的feed函数时,传递cat和pet1都能正常调用。这就是python中的多态。其实python中不支持重载函数,过多讨论多态也没太大的用处。