Files
paddlepaddle--paddle/test/dygraph_to_static/test_capture_free_vars.py
T
2026-07-13 12:40:42 +08:00

140 lines
3.6 KiB
Python

# Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
import numpy as np
from dygraph_to_static_utils import (
Dy2StTestBase,
)
import paddle
def create_simple_closure():
y = 1
def simple_closure(x):
return x + y
return simple_closure
class BaseLayer(paddle.nn.Layer):
def add_one(self, x):
y = x + 1
return y
class SuperCallWithoutArgumentInForward(BaseLayer):
def __init__(self):
super().__init__()
def forward(self, x):
# Actually, the super will use the free var `__class__` to
# call the `add_one` method.
return super().add_one(x)
class SuperCallWithoutArgumentInControlFlow(BaseLayer):
def __init__(self):
super().__init__()
def forward(self, x):
if x > 0:
return super().add_one(x)
else:
return x
class UserDefinedSuperCallWithoutArgument(BaseLayer):
def __init__(self):
super().__init__()
def forward(self, x):
def super():
class A:
def add_one(self, x):
return x + 1
return A()
return super().add_one(x)
class SuperCallWithArgument(BaseLayer):
def __init__(self):
super().__init__()
def forward(self, x):
y = super(__class__, self).add_one(x) # noqa: UP008
z = super(SuperCallWithArgument, self).add_one(y) # noqa: UP008
return z
def recursive_call(x):
if x == 1:
return 1
return x * recursive_call(x - 1)
class CheckDy2StWithDygraphMixin:
def check_fn(self, fn, *inputs):
dyres = fn(*inputs)
stres = paddle.jit.to_static(fn)(*inputs)
if isinstance(dyres, paddle.Tensor):
assert isinstance(stres, paddle.Tensor)
np.testing.assert_allclose(dyres.numpy(), stres.numpy())
else:
self.assertEqual(dyres, stres)
class TestClosure(Dy2StTestBase, CheckDy2StWithDygraphMixin):
def test_simple_closure(self):
simple_closure = create_simple_closure()
x = paddle.to_tensor(1.0)
self.check_fn(simple_closure, x)
class TestSuperCall(Dy2StTestBase, CheckDy2StWithDygraphMixin):
def test_super_call_without_argument_in_forward(self):
model = SuperCallWithoutArgumentInForward()
x = paddle.to_tensor(1.0)
self.check_fn(model, x)
def test_super_call_without_argument_in_control_flow(self):
model = SuperCallWithoutArgumentInControlFlow()
x = paddle.to_tensor(1.0)
self.check_fn(model, x)
def test_user_defined_super_call_without_argument(self):
model = UserDefinedSuperCallWithoutArgument()
x = paddle.to_tensor(1.0)
self.check_fn(model, x)
def test_super_call_with_argument(self):
model = SuperCallWithArgument()
x = paddle.to_tensor(1.0)
self.check_fn(model, x)
class TestRecursiveCall(Dy2StTestBase, CheckDy2StWithDygraphMixin):
def test_recursive_call(self):
x = 5
self.check_fn(recursive_call, x)
if __name__ == '__main__':
unittest.main()