In (!Address.isContract(address(this)) && _initialized == 1) I understand that !Address.isContract(address(this)) would be true from a constructor, but how would _initialized == 1 also be true then?
This allows constructors to call initializers. For example, if a contract inherits another contract and both have constructors with initializers, then _initialized == 1 due to the modifier having already been called in the parent constructor. See these two testcases: 12 and their test contracts for example.
Why would ppl write constructors with initializers? In my opinion, constructors can be run only once, which means it doesn't have to be constrained with initializer (can only run once)
You write a public function restricted by initializer, and then place all of your constructor code in that function, in order to allow its execution (once) every time the contract is upgraded.
Thanks for the reply, but could you take a moment and look into the test contracts example given by @ricglau above? In the given example, constructor is indeed constrained by initializer.
And I get it now, (!Address.isContract(address(this)) && _initialized == 1) is given only to be backward compatible since some minor versions back, there was not _disableInitializers() function, so in order to make upgradeable contracts safer by disabling initializers, the only way is to add Initializer modifier with the constructor. And the oz team is considering removing (!Address.isContract(address(this)) && _initialized == 1) and make a breaking change in the coming major version which is 0.5x