############### @property定义属性 ##############
# 所以对于定义属性你有好几种方式了和种类了,
# 静态属性,动态属性, # property
# 内置装饰器函数 只在面向对象中使用
# 注意:
# 1,不能传递任何的参数,
from math import pi
class Circle:
def __init__(self,r):
self.r = r
@property
def perimeter(self): # 不能传递任何的参数,周长和面积更加像一个属性,可以通过@property伪装成属性
return 2*pi*self.r
@property
def area(self):
return self.r**2*pi # c1 = Circle(5)
# print(c1.area) # 圆的面积
# print(c1.perimeter) # 圆的周长 ##########################################################
# 对@property装饰过的属性进行查看 修改 删除
# class Person:
# def __init__(self,name):
# self.__name = name
# self.price = 20
# @property
# def name(self):
# return self.__name
# @name.deleter # 用的很少
# def name(self):
# del self.__name # 这里面要有删除的操作,因为本质,@name.deleter,还是在执行函数,
# @name.setter # 注意必须要和@property装饰的函数的名字是一样的,只能传递一个参数,这样就是实现了对对象的修改,
# def name(self,new_name):
# self.__name = new_name
# brother2 = Person('二哥') # 实例化
# del Person.price # 删除了属性
# brother2.name = 'newName' #
# brother2
# del brother2.name
# print(brother2.name)
############### 静态方法和类方法 ##############
# method 方法
# staticmathod 静态的方法 ***
# classmethod 类方法 ****
# 类的操作行为
# class Goods:
# __discount = 0.8
# def __init__(self,name,price):
# self.name = name
# self.__price = price
# @property
# def price(self):
# return self.__price * Goods.__discount
# @classmethod # 把一个方法 变成一个类中的方法,这个方法就直接可以被类调用,不需要依托任何对象
# def change_discount(cls,new_discount): # 修改折扣要注意传递cls,
# cls.__discount = new_discount
# apple = Goods('苹果',5)
# print(apple.price)
# Goods.change_discount(0.5) # Goods.change_discount(Goods)
# print(apple.price)
# 当这个方法的操作只涉及静态属性的时候 就应该使用classmethod来装饰这个方法 #############################################
# 静态方法 class Login:
def __init__(self,name,password):
self.name = name
self.pwd = password
def login(self):pass @staticmethod
def get_usr_pwd(): # 静态方法,不需要传递self了,也不需要传递cls了,
usr = input('用户名 :')
pwd = input('密码 :')
Login(usr,pwd) Login.get_usr_pwd()
# 在完全面向对象的程序中,
# 如果一个函数 既和对象没有关系 也和类没有关系 那么就用staticmethod将这个函数变成一个静态方法 # 类方法和静态方法 都是类调用的,都是存储在类所在的内存中的,
# 对象可以调用类方法和静态方法么? 可以 一般情况下 推荐用类名调用
# 类方法 有一个默认参数 cls 代表这个类 cls
# 静态方法 没有默认的参数 就象函数一样
############### 反射 ##############
"""
反射: 什么是反射
反射是一个很重要的概念,它可以把字符串映射到实例的变量或者实例的方法然后可以去执行调用、修改等操作。它有四个重要的方法: getattr 获取指定字符串名称的对象属性
setattr 为对象设置一个对象
hasattr 判断对象是否有对应的对象(字符串)
delattr 删除指定属性 attr是属性英文的前几个字母,属性指的是类中类变量、实例变量和方法。但是要注意不能是私有的,如果你的变量是以“_”开头,那将无法获取。
反射常常用在动态加载模块的场景中。 """
"""
getattr() 函数:
getattr() 函数用于返回一个对象属性值。
getattr(object, name[, default]) object -- 对象。name -- 字符串,对象属性。
default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError hasattr() 函数用于判断对象是否包含对应的属性。
hasattr(object, name) object -- 对象。 name -- 字符串,属性名。
如果对象有该属性返回 True,否则返回 False。 setattr(object, name, value)
setattr() 函数对应函数 getattr(),用于设置属性值,该属性不一定是存在的。
object -- 对象。name -- 字符串,对象属性。value -- 属性值。 delattr 函数用于删除属性。
语法:delattr(object, name) -- 对象 name -- 必须是对象的属性。
delattr(x, 'foobar') 相等于 del x.foobar。object
""" class A(object):
bar = 1 def show(self):
print("这是一个普通方法") @classmethod
def dance(cls):
print("这是一个类方法") a = A()
print(getattr(A, 'bar')) # 获取属性 bar 值 1
print(getattr(a, 'bar')) # 获取属性 bar 值 1
ret = getattr(A, "dance")
print(ret) # <bound method A.dance of <class '__main__.A'>>,这是一个地址,
ret() # 加上括号就运行了,
"""
这就是反射:
1,通过一个字符串获取到了属性的值,
2,通过字符串拿到了函数地址,然后加括号就调用了,
""" # getattr(a, 'bar2') # 属性 bar2 不存在,触发异常,报错
# getattr(a, 'bar2', 3) # 属性 bar2 不存在,但设置了默认值
# 所以需要和hasattr进行配合使用,先判断是否有,然后再使用getattr
if hasattr(a, 'bar2'):
getattr(a, 'bar2')
############### 内置的类方法 ##############
"""
内置的类方法:
""" # 1,__ doc __表示类的描述信息
# class Foo:
# """ 描述类信息,这是用于看片的神奇 """
# def func(self):
# pass
# print(Foo.__doc__) #输出:类的描述信息 # 2.__ module __ 和 __ class __
# __ module __ 表示当前操作的对象在那个模块
# __ class__ 表示当前操作的对象的类是什么
# class C:
# def __init__(self):
# self.name = 'wupeiqi'
# # from lib.aa import C
# obj = C()
# print(obj.__module__) # 输出模块
# print(obj.__class__ ) # 输出类 # 3.__ init __
# 构造方法,通过类创建对象时,自动触发执行。 # 4.__ del __
# 析构方法,当对象在内存中被释放时,自动触发执行。
# 注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,
# 因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
# class Foo:
# def __del__(self):
# pass # 5.__call__
# 对象后面加括号,触发执行。
# 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于call方法的执行是由对象后加括号触发的,
# 即:对象()或者类()()
# class Foo:
# def __init__(self):
# pass
# def __call__(self, *args, **kwargs):
# print( '__call__')
# obj = Foo() # 执行 __init__
# obj() # 执行 __call__ # 6.__dict __
# 类或对象中的所有成员 上文中我们知道:类的普通字段属于对象;类中的静态字段和方法等属于类,
# 所以类名调用这个方法,会返回所有的静态字段和方法,对象名调用这个方法只会返回他的动态字段, # 7.__ str __
# 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。 # 8.__ iter __
# 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 iter
############### 单例模式 ##############
# __init__方法,是初始化方法
# __new__方法,构造方法,创建一个对象,
class A:
def __init__(self):
self.x = 1
print('in init function 对象初始化')
def __new__(cls, *args, **kwargs): # 这一定是传递的cls,因为这个时候还没有self,new就是创建self的机制,
print('in new function 创建对象,分配空间')
# return object.__new__(A) # 就是return了一个self,
return super().__new__(cls) # 重写一定要返回父类方法调用new方法的结果,这是一个静态方法,一定要主动传递cls,这个参数, a = A()
"""
a = A(),这句话是先执行的new方法,
in new function
in init function
"""
# print(a.x) #########################################
# new方法非常重要,用来实现单例模式:
# 单例模式:就是一个类只有一个实例,内存地址都是一样的,
# 什么是设计模式:
# 前人对问题的总结和提炼,通常设计模式就是对某一特定问题的成熟的解决方法。
# 这样工作中遇到这类问题,就不用思考怎么解决了,可以快速开发,并且提高代码的可靠性,
class A:
__instance= False # instance就是实例的意思,
def __init__(self,name,age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
if cls.__instance:
return cls.__instance
# cls.__instance = object.__new__(A)
cls.__instance = super().__new__(cls) # 重写一定要返回父类方法调用new方法的结果,这是一个静态方法,一定要主动传递cls,这个参数,
return cls.__instance ee = A("andy",11)
dd = A("mery",12) print(id(ee))
print(id(dd)) # 这两个内存地址是一样的,
############### 类的基本操作 ##############
############### 类的基本操作 ##############
############### 类的基本操作 ##############