2.类相关:
*dir(类名):查看类属性,返回形式是列表,列表前面的类似'__str__'的
属性都是系统内置的,自定义的属性与方法名会在列表的最后显示。
*__dict__:返回值['属性':'属性值','函数名':'函数地址',...]
类名.__dict__.['属性']-->属性值
类名.__dict__.['函数名'](参数)-->调用相对应的函数
*__name__:显示类名
*__doc__:显示类中的注释
3. 对象相关:对象=类名() #实现类对象的创建,有无参数取决于__init__()方法的参数!
4.类属性/实例属性
*类属性:类属性又称静态变量,与类对象进行绑定,但是不依赖类对象(依赖类本身),且独有一份!(相当于static修饰的变量)
*类属性的CRUD:
class Person:
name="pzz1"
def __init__(self):
pass
#查看
print(Person.name)
#添加
Person.age=10
print(Person.__dict__)
#修改
Person.age=1
print(Person.__dict__)
#删除
del Person.age
print(Person.__dict__)
*类方法的CRUD:
class Person:
name = "pzz1"
def __init__(self):
pass
def have_food(self,food):
print("Have %s"%food)
p1=Person()
#添加
def strong_body(self):
print("strong_body")
Person.strong=strong_body
p1.strong()
print(Person.__dict__)
#修改
def strong_body2(self):
print("strong_body2")
Person.strong=strong_body2
p1.strong()
print(Person.__dict__)
#删除
del Person.strong
print(Person.__dict__)
*实例属性:1.注意实例属性与类属性区别,实例属性是self.后面的属性,而类属性前面没有self,类属性可以理解为Java里面的静态属性!
2.实例还是可以调用类属性是因为静态变量的特点(静态变量有所有类对象共享,但是只有一份,依赖于类本身,不依赖类对象)
3.类对象只有实例属性,类属性与方法都是只有一份的,在类本身当中,而之所以类对象可以调用类方法,是因为类方法参数列表
中的self作用,类对象调用方法时,self会被初始化类对象的地址!从而实现类对象对类方法的调用!
实例属性的CRUD:
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def have_food(self):
print("Hava food!")
p1=Person("pzz",18)
#查看实例属性
print(p1.__dict__)
#添加实例属性
p1.gender="Boy"
print(p1.__dict__)
#修改实例属性
p1.gender="Girl"
print(p1.__dict__)
#删除实例属性
del p1.gender
print(p1.__dict__)
注意:实例的属性可以进行CRUD,方法也可以,但是一般不建议做!
5.实例属性/类属性/普通变量
注意点1:
name="-->>pzz1"
class Person:
name="pzz2" #属于类属性
def __init__(self,age,gender):
self.age=age
self.gender=gender #属于实例属性
print(name) #属于普通变量(***注意这个点,容易搞混)
p1=Person(18,"Boy")
print(p1.name,Person.name)
注意:1.类里面定义的变量是类属性,可以通过类名.__dict__的方式查看
2.__init__()方法里面的self.后面的属性属于实例属性,可以通过类对象.__dict__的方式查看
3.上述__init__()方法里面的name,不属于实例属性/类属性的任意一种,所以不会在实例和类里面查看,会去上一级直到全局查看!
注意点2:
class Person:
name="pzz1"
age=[1,2]
def __init__(self):
pass
p1=Person()
p1.name="pzz2" #注意这里面不会对类属性进行修改,只是增加了一个实例属性而已!
print("类属性-->%s"%Person.name,p1.name)
class Person:
name="pzz1"
age=[1,2]
def __init__(self):
pass
p1=Person()
p1.age.append(3) #修好了类属性
print("类属性-->%s"%Person.age,p1.age)
总结:一般情况下,做赋值操作的都不会修改类属性!
6.
*静态属性装饰器:@property
*静态方法装饰器:@staticmethod
*类方法装饰器:@classmethod
例子:
class Person:
name="pzz"
def __init__(self):
pass
@property
def have_food(self):
print("have_food")
@staticmethod
def have_food2(a,b):
print("have_food2",a,b)
@classmethod
def have_food3(cls):
print("have_food3",cls.name)
p1=Person()
#注意@property装饰方法,默认有参数self,在调用方法时,不需要加()
p1.have_food
#@staticmethod 静态方法,不能访问类属性与实例属性,就是一个类的工具包
#之所以不能访问类属性与实例属性,是因为该装饰器修饰的方法没有cls或是self默认参数
# 可以使用类名调用或是实例调用
Person.have_food2("apple","orange")
p1.have_food2("apple","orange")
#@classmethod 装饰器会给方法加上默认参数cls,方便访问类属性,类似self
#又因为类属性实例都可以访问,所以在实例调用该方法时,cls初始化为类对象,访问
#相应的属性与方法(类属性/类方法,实例都可以访问)
Person.have_food3()
p1.have_food3()
*继承:
1).子类继续父类的所有属性,但是如果子类定义的属性与父类属性重名,并不会覆盖,而是各自待在自己的__dict__中.
2).接口继承
import abc
#接口类,且方法必须全是抽象方法
#继承接口的类,全部实现抽象方法的是普通类,否则为抽象类
#抽象类是不可以创建对象的,当然接口也不可以
class Dad(metaclass=abc.ABCMeta):
@abc.abstractmethod
def make_money(self):
print("make money")
@abc.abstractmethod
def make_child(self):
print("make child")
3).继承顺序
*继承顺序参照类的MRO表(MRO表就是类的祖先)
*继承时,调用属性或是方法时,遵循的原则:
1.子类会优先于父类被检查
2.多个父类会依据它们在MRO表中的顺序
*Python3都是新式类,继承顺序遵循广度优先的原则;而在Python2中,有新式类与经典类之分
经典类:没有任何的基类(即class 类名:这种形式的,没有小括号的),但是经典类的子孙全是经典类!
继承顺序遵循深度优先原则,而且此类没有MRO列表!
新式类:存在任意基类!继承顺序同Python3!
4).子类调用父类的方法
class Dad():
def __init__(self,name,age):
self.name=name
self.age=age
def make_money(self):
print("Dad make money!")
class Son(Dad):
def __init__(self,name,age,gender):
#方式二:super(Son,self).__init__(name,age)
#方式三:Dad.__init__(self,name,age)
self.gender=gender
def consume_money(self):
#super().make_money()
#super(Son, self).make_money()
Dad.make_money(self)
print("Son consume money!")
注释:推荐方式一
*多态:多态的前提是继承,继承实现不同的对象拥有相同的方法,从而实现不同的类对象执行相同的方法(运行时的多态)
(理解的浅显,作者个人理解不透彻,请大牛多多指教)
*封装:
方式一:
class Dad:
_gender="Boy" #通过_方式,把变量约定为私有,但是类的外部依旧可以访问
def __init__(self,name,age):
self.name=name
self.age=age
def get_gender(self):
return self._gender
d1=Dad("plq",43)
print(d1.get_gender(),d1._gender)
方式二:
class Dad:
# 通过_方式,把变量约定为私有
# 类的外部不可以原样访问,但是可以通过_Dad__gender的方式访问.
#当变量被定义为__变量时,类会把其转换为_类名__变量!
#类的内部原样访问
__gender="Boy"
def __init__(self,name,age):
self.name=name
self.age=age
def get_gender(self):
return self.__gender
d1=Dad("plq",43)
print(d1.get_gender(),d1._Dad__gender)
9.反射
*定义:程序可以访问、检测和修改自身状态或行为的一种能力
*实现反射的函数:
hasattr(object,args):判断object中是否有参数argv对应的方法或是属性
getattr(object,name,default=None)
setattr(x,y,v)
delattr(x,y)
上述方法适应于类或是对象
class Dad:
gender="Boy"
def __init__(self,name,age):
self.name=name
self.age=age
def make_money(self):
print("make_money")
d1=Dad('plq',18)
#判断类或是实例中是否存在对应属性(方法)或是是否可以访问到对应属性(方法)!
# print(hasattr(d1,'gender'))
# print(hasattr(Dad,'gender'))
# print(hasattr(d1,'make_money'))
# print(hasattr(Dad,'make_money
#给类或是对象设置属性
setattr(d1,"hobby","basketball")
print(d1.__dict__)
setattr(Dad,"character","acute")
print(Dad.__dict__)
#给类或是对象设置方法
setattr(d1,"test1",lambda x:x+1)
setattr(Dad,"test2",lambda x:x-1)
#获得类或是对象的属性值(获取方法时,返回的是函数地址)
print(getattr(d1,"hobby"))
print(getattr(Dad,"character"))
getattr(d1,"make_money")()
getattr(Dad,"make_money")(d1)
#如果获取的属性或是方法不存在,错误信息提示是第三个参数的内容!
print(getattr(d1,"hobby1","没有hobby1属性"))
print(getattr(Dad,"character1","没有character1"))
#删除属性(或是方法)
delattr(d1,"hobby")
delattr(Dad,"character")
print(d1.__dict__)
print(Dad.__dict__)
面向对象编程详解
本文深入讲解面向对象编程的基础概念,包括类与对象的关系、属性与方法的管理、静态方法及属性的应用、组合与继承特性、多态与封装原理等。同时介绍了如何利用Python语言特性实现这些面向对象编程技巧。
264

被折叠的 条评论
为什么被折叠?



