一、再看property                                                                         

一个静态属性property本质就是实现了get,set,delete三种方法

 class Foo:
@property
def AAA(self):
print('get的时候运行我啊') @AAA.setter
def AAA(self,value):
print('set的时候运行我啊') @AAA.deleter
def AAA(self):
print('delete的时候运行我啊') #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA 用法一

用法1

 class Foo:
def get_AAA(self):
print('get的时候运行我啊') def set_AAA(self,value):
print('set的时候运行我啊') def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应 f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA 用法二

用法2

怎么用?

 class Goods:

     def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8 @property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price @price.setter
def price(self, value):
self.original_price = value @price.deleter
def price(self):
del self.original_price obj = Goods()
obj.price # 获取商品价格
obj.price = 200 # 修改商品原价
print(obj.price)
del obj.price # 删除商品原价 案例一

案例1

 #实现类型检测功能

 #第一关:
class People:
def __init__(self,name):
self.name=name @property
def name(self):
return self.name # p1=People('alex') #property自动实现了set和get方法属于数据描述符,比实例属性优先级高,所以你这面写会触发property内置的set,抛出异常 #第二关:修订版 class People:
def __init__(self,name):
self.name=name #实例化就触发property @property
def name(self):
# return self.name #无限递归
print('get------>')
return self.DouNiWan @name.setter
def name(self,value):
print('set------>')
self.DouNiWan=value @name.deleter
def name(self):
print('delete------>')
del self.DouNiWan p1=People('alex') #self.name实际是存放到self.DouNiWan里
print(p1.name)
print(p1.name)
print(p1.name)
print(p1.__dict__) p1.name='egon'
print(p1.__dict__) del p1.name
print(p1.__dict__) #第三关:加上类型检查
class People:
def __init__(self,name):
self.name=name #实例化就触发property @property
def name(self):
# return self.name #无限递归
print('get------>')
return self.DouNiWan @name.setter
def name(self,value):
print('set------>')
if not isinstance(value,str):
raise TypeError('必须是字符串类型')
self.DouNiWan=value @name.deleter
def name(self):
print('delete------>')
del self.DouNiWan p1=People('alex') #self.name实际是存放到self.DouNiWan里
p1.name=1 案例二

案例2

二、描述符(__get__,__set__,__delete__)                                 

1 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发

class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
def __get__(self, instance, owner):
pass
def __set__(self, instance, value):
pass
def __delete__(self, instance):
pass 定义一个描述符

定义一个描述符

2 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)

class Foo:
def __get__(self, instance, owner):
print('触发get')
def __set__(self, instance, value):
print('触发set')
def __delete__(self, instance):
print('触发delete') #包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法
f1=Foo()
f1.name='egon'
f1.name
del f1.name
#疑问:何时,何地,会触发这三个方法的执行 引子:描述符类产生的实例进行属性操作并不会触发三个方法的执行

引子:描述符类产生的实例进行属性操作并不会触发三个方法的执行

#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...') #描述符Int
class Int:
def __get__(self, instance, owner):
print('Int调用')
def __set__(self, instance, value):
print('Int设置...')
def __delete__(self, instance):
print('Int删除...') class People:
name=Str()
age=Int()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age #何地?:定义成另外一个类的类属性 #何时?:且看下列演示 p1=People('alex',18) #描述符Str的使用
p1.name
p1.name='egon'
del p1.name #描述符Int的使用
p1.age
p1.age=18
del p1.age #我们来瞅瞅到底发生了什么
print(p1.__dict__)
print(People.__dict__) #补充
print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__) 描述符应用之何时?何地?

描述符应用之何时?何地?

3 描述符分两种
一 数据描述符:至少实现了__get__()和__set__()

1 class Foo:
2 def __set__(self, instance, value):
3 print('set')
4 def __get__(self, instance, owner):
5 print('get')

二 非数据描述符:没有实现__set__()

1 class Foo:
2 def __get__(self, instance, owner):
3 print('get')

4 注意事项:
一 描述符本身应该定义成新式类,被代理的类也应该是新式类
二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
三 要严格遵循该优先级,优先级由高到底分别是
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()

#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...') class People:
name=Str()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age #基于上面的演示,我们已经知道,在一个类中定义描述符它就是一个类属性,存在于类的属性字典中,而不是实例的属性字典 #那既然描述符被定义成了一个类属性,直接通过类名也一定可以调用吧,没错
People.name #恩,调用类属性name,本质就是在调用描述符Str,触发了__get__() People.name='egon' #那赋值呢,我去,并没有触发__set__()
del People.name #赶紧试试del,我去,也没有触发__delete__()
#结论:描述符对类没有作用-------->傻逼到家的结论 '''
原因:描述符在使用时被定义成另外一个类的类属性,因而类属性比二次加工的描述符伪装而来的类属性有更高的优先级
People.name #恩,调用类属性name,找不到就去找描述符伪装的类属性name,触发了__get__() People.name='egon' #那赋值呢,直接赋值了一个类属性,它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的__set__()
del People.name #同上
''' 类属性>数据描述符

类属性>数据描述符

#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...') class People:
name=Str()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age p1=People('egon',18) #如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发描述符的操作,于p1本身无关了,相当于覆盖了实例的属性
p1.name='egonnnnnn'
p1.name
print(p1.__dict__)#实例的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是跟描述符有关,与实例无关了
del p1.name 数据描述符>实例属性

数据描述符>实例属性

class Foo:
def func(self):
print('我胡汉三又回来了')
f1=Foo()
f1.func() #调用类的方法,也可以说是调用非数据描述符
#函数是一个非数据描述符对象(一切皆对象么)
print(dir(Foo.func))
print(hasattr(Foo.func,'__set__'))
print(hasattr(Foo.func,'__get__'))
print(hasattr(Foo.func,'__delete__'))
#有人可能会问,描述符不都是类么,函数怎么算也应该是一个对象啊,怎么就是描述符了
#笨蛋哥,描述符是类没问题,描述符在应用的时候不都是实例化成一个类属性么
#函数就是一个由非描述符类实例化得到的对象
#没错,字符串也一样 f1.func='这是实例属性啊'
print(f1.func) del f1.func #删掉了非数据
f1.func() 实例属性>非数据描述符

实例属性>非数据描述符

class Foo:
def __set__(self, instance, value):
print('set')
def __get__(self, instance, owner):
print('get')
class Room:
name=Foo()
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length #name是一个数据描述符,因为name=Foo()而Foo实现了get和set方法,因而比实例属性有更高的优先级
#对实例的属性操作,触发的都是描述符的
r1=Room('厕所',1,1)
r1.name
r1.name='厨房' class Foo:
def __get__(self, instance, owner):
print('get')
class Room:
name=Foo()
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length #name是一个非数据描述符,因为name=Foo()而Foo没有实现set方法,因而比实例属性有更低的优先级
#对实例的属性操作,触发的都是实例自己的
r1=Room('厕所',1,1)
r1.name
r1.name='厨房' 再次验证:实例属性>非数据描述符

再次验证:实例属性>非数据描述符

class Foo:
def func(self):
print('我胡汉三又回来了') def __getattr__(self, item):
print('找不到了当然是来找我啦',item)
f1=Foo() f1.xxxxxxxxxxx 非数据描述符>找不到

非数据描述符>找不到

5 描述符使用

众所周知,python是弱类型语言,即参数的赋值没有类型限制,下面我们通过描述符机制来实现类型限制功能

 class Str:
def __init__(self,name):
self.name=name
def __get__(self, instance, owner):
print('get--->',instance,owner)
return instance.__dict__[self.name] def __set__(self, instance, value):
print('set--->',instance,value)
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name) class People:
name=Str('name')
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary p1=People('egon',18,3231.3) #调用
print(p1.__dict__)
p1.name #赋值
print(p1.__dict__)
p1.name='egonlin'
print(p1.__dict__) #删除
print(p1.__dict__)
del p1.name
print(p1.__dict__) 牛刀小试

牛刀小试

 class Str:
def __init__(self,name):
self.name=name
def __get__(self, instance, owner):
print('get--->',instance,owner)
return instance.__dict__[self.name] def __set__(self, instance, value):
print('set--->',instance,value)
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name) class People:
name=Str('name')
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary #疑问:如果我用类名去操作属性呢
People.name #报错,错误的根源在于类去操作属性时,会把None传给instance #修订__get__方法
class Str:
def __init__(self,name):
self.name=name
def __get__(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.__dict__[self.name] def __set__(self, instance, value):
print('set--->',instance,value)
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name) class People:
name=Str('name')
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
print(People.name) #完美,解决 拔刀相助

拔刀相助

 class Str:
def __init__(self,name,expected_type):
self.name=name
self.expected_type=expected_type
def __get__(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.__dict__[self.name] def __set__(self, instance, value):
print('set--->',instance,value)
if not isinstance(value,self.expected_type): #如果不是期望的类型,则抛出异常
raise TypeError('Expected %s' %str(self.expected_type))
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name) class People:
name=Str('name',str) #新增类型限制str
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary p1=People(123,18,3333.3)#传入的name因不是字符串类型而抛出异常 磨刀霍霍

磨刀霍霍

 class Typed:
def __init__(self,name,expected_type):
self.name=name
self.expected_type=expected_type
def __get__(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.__dict__[self.name] def __set__(self, instance, value):
print('set--->',instance,value)
if not isinstance(value,self.expected_type):
raise TypeError('Expected %s' %str(self.expected_type))
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name) class People:
name=Typed('name',str)
age=Typed('name',int)
salary=Typed('name',float)
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary p1=People(123,18,3333.3)
p1=People('egon','',3333.3)
p1=People('egon',18,3333) 大刀阔斧

大刀阔斧

大刀阔斧之后我们已然能实现功能了,但是问题是,如果我们的类有很多属性,你仍然采用在定义一堆类属性的方式去实现,low,这时候我需要教你一招:独孤九剑

def decorate(cls):
print('类的装饰器开始运行啦------>')
return cls @decorate #无参:People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary p1=People('egon',18,3333.3) 类的装饰器:无参

类的装饰器:无参

def typeassert(**kwargs):
def decorate(cls):
print('类的装饰器开始运行啦------>',kwargs)
return cls
return decorate
@typeassert(name=str,age=int,salary=float) #有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary p1=People('egon',18,3333.3) 类的装饰器:有参

类的装饰器:有参

终极大招

 class Typed:
def __init__(self,name,expected_type):
self.name=name
self.expected_type=expected_type
def __get__(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.__dict__[self.name] def __set__(self, instance, value):
print('set--->',instance,value)
if not isinstance(value,self.expected_type):
raise TypeError('Expected %s' %str(self.expected_type))
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name) def typeassert(**kwargs):
def decorate(cls):
print('类的装饰器开始运行啦------>',kwargs)
for name,expected_type in kwargs.items():
setattr(cls,name,Typed(name,expected_type))
return cls
return decorate
@typeassert(name=str,age=int,salary=float) #有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary print(People.__dict__)
p1=People('egon',18,3333.3) 刀光剑影

刀光剑影

6 描述符总结

描述符是可以实现大部分python类特性中的底层魔法,包括@classmethod,@staticmethd,@property甚至是__slots__属性

描述父是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件.

7 利用描述符原理完成一个自定制@property,实现延迟计算(本质就是把一个函数属性利用装饰器原理做成一个描述符:类的属性字典中函数名为key,value为描述符类产生的对象)

class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length @property
def area(self):
return self.width * self.length r1=Room('alex',1,1)
print(r1.area) @property回顾

@property回顾

class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
if instance is None:
return self
return self.func(instance) #此时你应该明白,到底是谁在为你做自动传递self的事情 class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length @Lazyproperty #area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
def area(self):
return self.width * self.length r1=Room('alex',1,1)
print(r1.area) 自己做一个@property

自己做一个@property

class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
if instance is None:
return self
else:
print('--->')
value=self.func(instance)
setattr(instance,self.func.__name__,value) #计算一次就缓存到实例的属性字典中
return value class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length @Lazyproperty #area=Lazyproperty(area) 相当于'定义了一个类属性,即描述符'
def area(self):
return self.width * self.length r1=Room('alex',1,1)
print(r1.area) #先从自己的属性字典找,没有再去类的中找,然后出发了area的__get__方法
print(r1.area) #先从自己的属性字典找,找到了,是上次计算的结果,这样就不用每执行一次都去计算 实现延迟计算功能

实现延迟计算功能

#缓存不起来了

class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
if instance is None:
return self
else:
value=self.func(instance)
instance.__dict__[self.func.__name__]=value
return value
# return self.func(instance) #此时你应该明白,到底是谁在为你做自动传递self的事情
def __set__(self, instance, value):
print('hahahahahah') class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length @Lazyproperty #area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
def area(self):
return self.width * self.length print(Room.__dict__)
r1=Room('alex',1,1)
print(r1.area)
print(r1.area)
print(r1.area)
print(r1.area) #缓存功能失效,每次都去找描述符了,为何,因为描述符实现了set方法,它由非数据描述符变成了数据描述符,数据描述符比实例属性有更高的优先级,因而所有的属性操作都去找描述符了 一个小的改动,延迟计算的美梦就破碎了

一个小的改动,延迟计算的美梦就破碎了

8 利用描述符原理完成一个自定制@classmethod

class ClassMethod:
def __init__(self,func):
self.func=func def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback():
print('在这里可以加功能啊...')
return self.func(owner)
return feedback class People:
name='linhaifeng'
@ClassMethod # say_hi=ClassMethod(say_hi)
def say_hi(cls):
print('你好啊,帅哥 %s' %cls.name) People.say_hi() p1=People()
p1.say_hi()
#疑问,类方法如果有参数呢,好说,好说 class ClassMethod:
def __init__(self,func):
self.func=func def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback(*args,**kwargs):
print('在这里可以加功能啊...')
return self.func(owner,*args,**kwargs)
return feedback class People:
name='linhaifeng'
@ClassMethod # say_hi=ClassMethod(say_hi)
def say_hi(cls,msg):
print('你好啊,帅哥 %s %s' %(cls.name,msg)) People.say_hi('你是那偷心的贼') p1=People()
p1.say_hi('你是那偷心的贼') 自己做一个@classmethod

自己做一个@classmethod

9 利用描述符原理完成一个自定制的@staticmethod

class StaticMethod:
def __init__(self,func):
self.func=func def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback(*args,**kwargs):
print('在这里可以加功能啊...')
return self.func(*args,**kwargs)
return feedback class People:
@StaticMethod# say_hi=StaticMethod(say_hi)
def say_hi(x,y,z):
print('------>',x,y,z) People.say_hi(1,2,3) p1=People()
p1.say_hi(4,5,6) 自己做一个@staticmethod

自己做一个@staticmethod

详情见:http://www.cnblogs.com/linhaifeng/articles/6204014.html#_label7

python基础----再看property、描述符(__get__,__set__,__delete__)的更多相关文章

  1. 描述符__get__,__set__,__delete__和析构方法__del__

    描述符__get__,__set__,__delete__ 1.描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一 ...

  2. 描述符__get__,__set__,__delete__

    描述符__get__,__set__,__delete__ # 描述符:1用来代理另外一个类的属性 # __get__():调用一个属性时,触发 # __set__():为一个属性赋值时触发 # __ ...

  3. 描述符__get__(),__set__(),__delete__()(三十七)

    http://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__ ...

  4. Python描述符(__get__,__set__,__delete__)简介

    先说定义,这里直接翻译官方英文文档: 一般来说,描述符是具有“绑定行为”的对象属性,该对象的属性访问将会被描述符协议中的方法覆盖.这些方法是__get__(),__set__(),和__delete_ ...

  5. python小知识-__call__和类装饰器的结合使用,数据描述符__get__\__set__\__delete__(描述符类是Python中一种用于储存类属性值的对象)

    class Decorator(): def __init__(self, f): print('run in init......') self.f = f def __call__(self, a ...

  6. Python类总结-描述符__get__(),__set__(),__delete__()

    1 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),set(),delete()中的一个,这也被称为描述符协议 get():调用一个属性时,触发 set():为一 ...

  7. python基础——特性(property)、静态方法(staticmethod)和类方法(classmethod)

    python基础--特性(property) 1 什么是特性property property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值 import math class Circl ...

  8. __get__ __set__ __delete__描述符

    描述符就是一个新式类,这个类至少要实现__get__ __set__ __delete__方法中的一种class Foo: def __get__(self, instance, owner): pr ...

  9. Python全栈day28(描述符应用)

    描述符的使用 python是弱类型语言,及参数的赋值没有类型限制,下面通过描述符机制来实现类型限制功能 描述符应用1.py class Typed: def __get__(self, instanc ...

随机推荐

  1. CentOS 7.2二进制安装mysql-5.7.19

    官方文档地址:https://dev.mysql.com/doc/refman/5.7/en/binary-installation.html 开始安装 1.下载mysql二进制包 # cd /usr ...

  2. NO.02---聊聊Vue提升

    如果本篇有看不明白的地方,请翻阅上一篇文章 上一篇我们讲了如何通过一些简单的动作来改变 store.js 中的数据对象,在实际工作中,这是完全无法满足工作需求的,所以这篇我们来说说如何做一些简单的流程 ...

  3. Teaching Machines to Understand Us 让机器理解我们 之一 引言

    Teaching Machines to Understand Us   By Tom Simonite  MIT Technology Review Vol.118 No.5 2015 让机器理解我 ...

  4. CentOS7使用阿里源安装最新版Docker

    卸载已经安装的Docker sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker ...

  5. 【python 3.6】xlwt和xlrd对excel的读写操作

    #python 3.6 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'BH8ANK' import xlrd '''====== ...

  6. vs2017搭建linux c++开发环境

    最近一直在阅读ovs的源码,看到用户态代码的时候,需要对用户态的代码进行调试,一开始想直接使用linux中的GDB进行调试,但是ovs的工程太过于复杂,从网上找了些文章,发现vs2017能够支持lin ...

  7. hbase 修复 hbck

    hbase 修复使用hbck 新版本的 hbck 可以修复各种错误,修复选项是: (1)-fix,向下兼容用,被-fixAssignments替代 (2)-fixAssignments,用于修复reg ...

  8. $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 区别

    PHP $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 的区别 PHP $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 通常情况下,PHP ...

  9. "Hello World!"团队第十次会议

    Scrum会议 今天是我们"Hello World!"团队第十次召开会议,博客内容是: 1.会议时间 2.会议成员 3.会议地点 4.会议内容 5.todo list 6.会议照片 ...

  10. 软工实践-Alpha 冲刺 (4/10)

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 很胖,刚学,照猫画虎做了登录与注册界面. 展示GitHub ...